diff --git a/.gitignore b/.gitignore
index 89cc712a..17a319a4 100644
--- a/.gitignore
+++ b/.gitignore
@@ -6,5 +6,4 @@ out/
 build/
 
 
-!gradle-wrapper.jar
-gradle.properties
\ No newline at end of file
+!gradle-wrapper.jar
\ No newline at end of file
diff --git a/CHANGELOG.md b/CHANGELOG.md
new file mode 100644
index 00000000..5018fb97
--- /dev/null
+++ b/CHANGELOG.md
@@ -0,0 +1,39 @@
+# Changelog
+
+## [Unreleased]
+### Added
+
+### Changed
+
+### Deprecated
+
+### Removed
+
+### Fixed
+
+### Security
+## [0.2.0]
+### Added
+
+### Changed
+- Context content resolution refactor
+- Kotlin 1.4.10 (build tools 0.6.0)
+- Empty query in Name is null instead of ""
+- Provider provides an empty map instead of error by default
+- Hidden delegates hierarchy in favor of stdlib properties
+- Removed io depdendency from `dataforge-output`. Replaced Output by Appendable.
+- Configurable is no longer MutableItemProvider. All functionality moved to Scheme.
+
+### Deprecated
+- Context activation API
+- TextRenderer
+
+### Removed
+- Functional server prototype
+- `dataforge-output` module
+
+### Fixed
+- Global context CoroutineScope resolution
+- Library mode compliance
+
+### Security
diff --git a/build.gradle.kts b/build.gradle.kts
index ac454902..7d138083 100644
--- a/build.gradle.kts
+++ b/build.gradle.kts
@@ -1,27 +1,24 @@
-
 plugins {
-    val toolsVersion = "0.5.0"
-    id("scientifik.mpp") version toolsVersion apply false
-    id("scientifik.jvm") version toolsVersion apply false
-    id("scientifik.publish") version toolsVersion apply false
-    id("org.jetbrains.dokka") version "0.10.1"
+    id("ru.mipt.npm.project")
 }
 
-val dataforgeVersion by extra("0.1.8")
+val dataforgeVersion by extra("0.2.0")
 
 val bintrayRepo by extra("dataforge")
 val githubProject by extra("dataforge-core")
+val spaceRepo by extra("https://maven.jetbrains.space/mipt-npm/p/df/maven")
 
 allprojects {
     group = "hep.dataforge"
     version = dataforgeVersion
 
+    apply<org.jetbrains.dokka.gradle.DokkaPlugin>()
+
     repositories {
         mavenLocal()
     }
 }
 
 subprojects {
-    apply(plugin = "scientifik.publish")
-    apply(plugin = "org.jetbrains.dokka")
+    apply(plugin = "ru.mipt.npm.publish")
 }
\ No newline at end of file
diff --git a/dataforge-context/api/dataforge-context.api b/dataforge-context/api/dataforge-context.api
new file mode 100644
index 00000000..39fa72d8
--- /dev/null
+++ b/dataforge-context/api/dataforge-context.api
@@ -0,0 +1,334 @@
+public abstract class hep/dataforge/context/AbstractPlugin : hep/dataforge/context/Plugin {
+	public fun <init> ()V
+	public fun <init> (Lhep/dataforge/meta/Meta;)V
+	public synthetic fun <init> (Lhep/dataforge/meta/Meta;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
+	public fun attach (Lhep/dataforge/context/Context;)V
+	public fun content (Ljava/lang/String;)Ljava/util/Map;
+	public synthetic fun dependsOn ()Ljava/util/Collection;
+	public final fun dependsOn ()Ljava/util/List;
+	public fun detach ()V
+	public fun getContext ()Lhep/dataforge/context/Context;
+	public fun getDefaultChainTarget ()Ljava/lang/String;
+	public fun getDefaultTarget ()Ljava/lang/String;
+	public fun getLogger ()Lmu/KLogger;
+	public fun getMeta ()Lhep/dataforge/meta/Meta;
+	public fun getName ()Lhep/dataforge/names/Name;
+	protected final fun require (Lhep/dataforge/context/PluginFactory;)Lkotlin/properties/ReadOnlyProperty;
+	public fun toMeta ()Lhep/dataforge/meta/Meta;
+}
+
+public final class hep/dataforge/context/AbstractPluginKt {
+	public static final fun toMap (Ljava/util/Collection;)Ljava/util/Map;
+}
+
+public final class hep/dataforge/context/ClassLoaderPlugin : hep/dataforge/context/AbstractPlugin {
+	public static final field Companion Lhep/dataforge/context/ClassLoaderPlugin$Companion;
+	public fun <init> (Ljava/lang/ClassLoader;)V
+	public fun getTag ()Lhep/dataforge/context/PluginTag;
+	public final fun services (Lkotlin/reflect/KClass;)Lkotlin/sequences/Sequence;
+}
+
+public final class hep/dataforge/context/ClassLoaderPlugin$Companion {
+	public final fun getDEFAULT ()Lhep/dataforge/context/ClassLoaderPlugin;
+}
+
+public final class hep/dataforge/context/ClassLoaderPluginKt {
+	public static final fun getClassLoaderPlugin (Lhep/dataforge/context/Context;)Lhep/dataforge/context/ClassLoaderPlugin;
+}
+
+public class hep/dataforge/context/Context : hep/dataforge/context/Named, hep/dataforge/meta/MetaRepr, hep/dataforge/provider/Provider, kotlinx/coroutines/CoroutineScope {
+	public static final field Companion Lhep/dataforge/context/Context$Companion;
+	public static final field PROPERTY_TARGET Ljava/lang/String;
+	public fun <init> (Lhep/dataforge/names/Name;Lhep/dataforge/context/Context;Lhep/dataforge/meta/Meta;Ljava/util/Set;)V
+	public synthetic fun <init> (Lhep/dataforge/names/Name;Lhep/dataforge/context/Context;Lhep/dataforge/meta/Meta;Ljava/util/Set;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
+	public fun close ()V
+	public fun content (Ljava/lang/String;)Ljava/util/Map;
+	public final fun content (Ljava/lang/String;Z)Ljava/util/Map;
+	public fun getCoroutineContext ()Lkotlin/coroutines/CoroutineContext;
+	public fun getDefaultChainTarget ()Ljava/lang/String;
+	public fun getDefaultTarget ()Ljava/lang/String;
+	public final fun getLogger ()Lmu/KLogger;
+	public final fun getName ()Lhep/dataforge/names/Name;
+	public final fun getParent ()Lhep/dataforge/context/Context;
+	public final fun getPlugins ()Lhep/dataforge/context/PluginManager;
+	public fun toMeta ()Lhep/dataforge/meta/Meta;
+}
+
+public final class hep/dataforge/context/Context$Companion {
+}
+
+public abstract interface class hep/dataforge/context/ContextAware {
+	public abstract fun getContext ()Lhep/dataforge/context/Context;
+	public abstract fun getLogger ()Lmu/KLogger;
+}
+
+public final class hep/dataforge/context/ContextAware$DefaultImpls {
+	public static fun getLogger (Lhep/dataforge/context/ContextAware;)Lmu/KLogger;
+}
+
+public final class hep/dataforge/context/ContextBuilder {
+	public fun <init> ()V
+	public fun <init> (Lhep/dataforge/context/Context;Ljava/lang/String;)V
+	public synthetic fun <init> (Lhep/dataforge/context/Context;Ljava/lang/String;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
+	public final fun build ()Lhep/dataforge/context/Context;
+	public final fun getName ()Ljava/lang/String;
+	public final fun plugin (Lhep/dataforge/context/Plugin;)V
+	public final fun plugin (Lhep/dataforge/context/PluginFactory;Lkotlin/jvm/functions/Function1;)V
+	public final fun plugin (Lhep/dataforge/context/PluginTag;Lkotlin/jvm/functions/Function1;)V
+	public final fun plugin (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Lkotlin/jvm/functions/Function1;)V
+	public static synthetic fun plugin$default (Lhep/dataforge/context/ContextBuilder;Lhep/dataforge/context/PluginFactory;Lkotlin/jvm/functions/Function1;ILjava/lang/Object;)V
+	public static synthetic fun plugin$default (Lhep/dataforge/context/ContextBuilder;Lhep/dataforge/context/PluginTag;Lkotlin/jvm/functions/Function1;ILjava/lang/Object;)V
+	public static synthetic fun plugin$default (Lhep/dataforge/context/ContextBuilder;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Lkotlin/jvm/functions/Function1;ILjava/lang/Object;)V
+	public final fun properties (Lkotlin/jvm/functions/Function1;)V
+	public final fun setName (Ljava/lang/String;)V
+}
+
+public abstract interface class hep/dataforge/context/Factory {
+	public abstract fun invoke (Lhep/dataforge/meta/Meta;Lhep/dataforge/context/Context;)Ljava/lang/Object;
+}
+
+public final class hep/dataforge/context/Factory$DefaultImpls {
+	public static synthetic fun invoke$default (Lhep/dataforge/context/Factory;Lhep/dataforge/meta/Meta;Lhep/dataforge/context/Context;ILjava/lang/Object;)Ljava/lang/Object;
+}
+
+public final class hep/dataforge/context/Global : hep/dataforge/context/Context {
+	public static final field INSTANCE Lhep/dataforge/context/Global;
+	public fun close ()V
+	public final fun context (Ljava/lang/String;Lhep/dataforge/context/Context;Lkotlin/jvm/functions/Function1;)Lhep/dataforge/context/Context;
+	public static synthetic fun context$default (Lhep/dataforge/context/Global;Ljava/lang/String;Lhep/dataforge/context/Context;Lkotlin/jvm/functions/Function1;ILjava/lang/Object;)Lhep/dataforge/context/Context;
+	public final fun getContext (Ljava/lang/String;)Lhep/dataforge/context/Context;
+	public fun getCoroutineContext ()Lkotlin/coroutines/CoroutineContext;
+}
+
+public abstract interface class hep/dataforge/context/Named {
+	public static final field Companion Lhep/dataforge/context/Named$Companion;
+	public abstract fun getName ()Lhep/dataforge/names/Name;
+}
+
+public final class hep/dataforge/context/Named$Companion {
+	public final fun nameOf (Ljava/lang/Object;)Lhep/dataforge/names/Name;
+}
+
+public final class hep/dataforge/context/NamedKt {
+	public static final fun isAnonymous (Lhep/dataforge/context/Named;)Z
+}
+
+public abstract interface class hep/dataforge/context/Plugin : hep/dataforge/context/ContextAware, hep/dataforge/context/Named, hep/dataforge/meta/MetaRepr, hep/dataforge/provider/Provider {
+	public static final field Companion Lhep/dataforge/context/Plugin$Companion;
+	public static final field TARGET Ljava/lang/String;
+	public abstract fun attach (Lhep/dataforge/context/Context;)V
+	public abstract fun dependsOn ()Ljava/util/Collection;
+	public abstract fun detach ()V
+	public abstract fun getMeta ()Lhep/dataforge/meta/Meta;
+	public abstract fun getName ()Lhep/dataforge/names/Name;
+	public abstract fun getTag ()Lhep/dataforge/context/PluginTag;
+	public abstract fun toMeta ()Lhep/dataforge/meta/Meta;
+}
+
+public final class hep/dataforge/context/Plugin$Companion {
+	public static final field TARGET Ljava/lang/String;
+}
+
+public final class hep/dataforge/context/Plugin$DefaultImpls {
+	public static fun content (Lhep/dataforge/context/Plugin;Ljava/lang/String;)Ljava/util/Map;
+	public static fun getDefaultChainTarget (Lhep/dataforge/context/Plugin;)Ljava/lang/String;
+	public static fun getDefaultTarget (Lhep/dataforge/context/Plugin;)Ljava/lang/String;
+	public static fun getLogger (Lhep/dataforge/context/Plugin;)Lmu/KLogger;
+	public static fun getName (Lhep/dataforge/context/Plugin;)Lhep/dataforge/names/Name;
+	public static fun toMeta (Lhep/dataforge/context/Plugin;)Lhep/dataforge/meta/Meta;
+}
+
+public abstract interface class hep/dataforge/context/PluginFactory : hep/dataforge/context/Factory {
+	public static final field Companion Lhep/dataforge/context/PluginFactory$Companion;
+	public static final field TYPE Ljava/lang/String;
+	public abstract fun getTag ()Lhep/dataforge/context/PluginTag;
+	public abstract fun getType ()Lkotlin/reflect/KClass;
+}
+
+public final class hep/dataforge/context/PluginFactory$Companion {
+	public static final field TYPE Ljava/lang/String;
+}
+
+public final class hep/dataforge/context/PluginManager : hep/dataforge/context/ContextAware, java/lang/Iterable, kotlin/jvm/internal/markers/KMappedMarker {
+	public fun <init> (Lhep/dataforge/context/Context;Ljava/util/Set;)V
+	public final fun fetch (Lhep/dataforge/context/PluginFactory;ZLhep/dataforge/meta/Meta;)Lhep/dataforge/context/Plugin;
+	public final fun fetch (Lhep/dataforge/context/PluginFactory;ZLkotlin/jvm/functions/Function1;)Lhep/dataforge/context/Plugin;
+	public static synthetic fun fetch$default (Lhep/dataforge/context/PluginManager;Lhep/dataforge/context/PluginFactory;ZLhep/dataforge/meta/Meta;ILjava/lang/Object;)Lhep/dataforge/context/Plugin;
+	public static synthetic fun fetch$default (Lhep/dataforge/context/PluginManager;Lhep/dataforge/context/PluginFactory;ZLkotlin/jvm/functions/Function1;ILjava/lang/Object;)Lhep/dataforge/context/Plugin;
+	public final fun find (ZLkotlin/jvm/functions/Function1;)Lhep/dataforge/context/Plugin;
+	public static synthetic fun find$default (Lhep/dataforge/context/PluginManager;ZLkotlin/jvm/functions/Function1;ILjava/lang/Object;)Lhep/dataforge/context/Plugin;
+	public final fun get (Lhep/dataforge/context/PluginTag;Z)Lhep/dataforge/context/Plugin;
+	public final fun get (Lkotlin/reflect/KClass;Lhep/dataforge/context/PluginTag;Z)Ljava/lang/Object;
+	public static synthetic fun get$default (Lhep/dataforge/context/PluginManager;Lhep/dataforge/context/PluginTag;ZILjava/lang/Object;)Lhep/dataforge/context/Plugin;
+	public static synthetic fun get$default (Lhep/dataforge/context/PluginManager;Lkotlin/reflect/KClass;Lhep/dataforge/context/PluginTag;ZILjava/lang/Object;)Ljava/lang/Object;
+	public fun getContext ()Lhep/dataforge/context/Context;
+	public fun getLogger ()Lmu/KLogger;
+	public fun iterator ()Ljava/util/Iterator;
+	public final fun list (Z)Ljava/util/Collection;
+	public final fun load (Lhep/dataforge/context/Plugin;)Lhep/dataforge/context/Plugin;
+	public final fun load (Lhep/dataforge/context/PluginFactory;Lhep/dataforge/meta/Meta;)Lhep/dataforge/context/Plugin;
+	public final fun load (Lhep/dataforge/context/PluginFactory;Lkotlin/jvm/functions/Function1;)Lhep/dataforge/context/Plugin;
+	public static synthetic fun load$default (Lhep/dataforge/context/PluginManager;Lhep/dataforge/context/PluginFactory;Lhep/dataforge/meta/Meta;ILjava/lang/Object;)Lhep/dataforge/context/Plugin;
+	public final fun remove (Lhep/dataforge/context/Plugin;)V
+}
+
+public final class hep/dataforge/context/PluginTag : hep/dataforge/meta/MetaRepr {
+	public static final field Companion Lhep/dataforge/context/PluginTag$Companion;
+	public static final field DATAFORGE_GROUP Ljava/lang/String;
+	public fun <init> (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V
+	public synthetic fun <init> (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
+	public final fun component1 ()Ljava/lang/String;
+	public final fun component2 ()Ljava/lang/String;
+	public final fun component3 ()Ljava/lang/String;
+	public final fun copy (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)Lhep/dataforge/context/PluginTag;
+	public static synthetic fun copy$default (Lhep/dataforge/context/PluginTag;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;ILjava/lang/Object;)Lhep/dataforge/context/PluginTag;
+	public fun equals (Ljava/lang/Object;)Z
+	public final fun getGroup ()Ljava/lang/String;
+	public final fun getName ()Ljava/lang/String;
+	public final fun getVersion ()Ljava/lang/String;
+	public fun hashCode ()I
+	public final fun matches (Lhep/dataforge/context/PluginTag;)Z
+	public fun toMeta ()Lhep/dataforge/meta/Meta;
+	public fun toString ()Ljava/lang/String;
+}
+
+public final class hep/dataforge/context/PluginTag$Companion {
+	public final fun fromString (Ljava/lang/String;)Lhep/dataforge/context/PluginTag;
+}
+
+public final class hep/dataforge/context/ResolveKt {
+	public static final fun gather (Lhep/dataforge/context/Context;Ljava/lang/String;Lkotlin/reflect/KClass;Z)Ljava/util/Map;
+	public static synthetic fun gather$default (Lhep/dataforge/context/Context;Ljava/lang/String;Lkotlin/reflect/KClass;ZILjava/lang/Object;)Ljava/util/Map;
+	public static final fun gatherInSequence (Lhep/dataforge/context/Context;Ljava/lang/String;Lkotlin/reflect/KClass;Z)Lkotlin/sequences/Sequence;
+	public static synthetic fun gatherInSequence$default (Lhep/dataforge/context/Context;Ljava/lang/String;Lkotlin/reflect/KClass;ZILjava/lang/Object;)Lkotlin/sequences/Sequence;
+	public static final fun getValues (Lkotlin/sequences/Sequence;)Lkotlin/sequences/Sequence;
+	public static final fun resolve (Lhep/dataforge/context/Context;Ljava/lang/String;Lhep/dataforge/names/Name;Lkotlin/reflect/KClass;)Ljava/lang/Object;
+}
+
+public abstract interface annotation class hep/dataforge/descriptors/Attribute : java/lang/annotation/Annotation {
+	public abstract fun key ()Ljava/lang/String;
+	public abstract fun value ()Ljava/lang/String;
+}
+
+public abstract interface annotation class hep/dataforge/descriptors/Attributes : java/lang/annotation/Annotation {
+	public abstract fun attrs ()[Lhep/dataforge/descriptors/Attribute;
+}
+
+public abstract interface annotation class hep/dataforge/descriptors/ItemDef : java/lang/annotation/Annotation {
+	public abstract fun info ()Ljava/lang/String;
+	public abstract fun multiple ()Z
+	public abstract fun required ()Z
+}
+
+public abstract interface annotation class hep/dataforge/descriptors/ValueDef : java/lang/annotation/Annotation {
+	public abstract fun allowed ()[Ljava/lang/String;
+	public abstract fun def ()Ljava/lang/String;
+	public abstract fun enumeration ()Ljava/lang/Class;
+	public abstract fun type ()[Lhep/dataforge/values/ValueType;
+}
+
+public final class hep/dataforge/properties/ConfigProperty : hep/dataforge/properties/Property {
+	public fun <init> (Lhep/dataforge/meta/Config;Lhep/dataforge/names/Name;Lhep/dataforge/meta/transformations/MetaConverter;)V
+	public final fun getConfig ()Lhep/dataforge/meta/Config;
+	public final fun getConverter ()Lhep/dataforge/meta/transformations/MetaConverter;
+	public final fun getName ()Lhep/dataforge/names/Name;
+	public fun getValue ()Ljava/lang/Object;
+	public fun onChange (Ljava/lang/Object;Lkotlin/jvm/functions/Function1;)V
+	public fun removeChangeListener (Ljava/lang/Object;)V
+	public fun setValue (Ljava/lang/Object;)V
+}
+
+public abstract interface class hep/dataforge/properties/Property {
+	public abstract fun getValue ()Ljava/lang/Object;
+	public abstract fun onChange (Ljava/lang/Object;Lkotlin/jvm/functions/Function1;)V
+	public abstract fun removeChangeListener (Ljava/lang/Object;)V
+	public abstract fun setValue (Ljava/lang/Object;)V
+}
+
+public final class hep/dataforge/properties/Property$DefaultImpls {
+	public static synthetic fun onChange$default (Lhep/dataforge/properties/Property;Ljava/lang/Object;Lkotlin/jvm/functions/Function1;ILjava/lang/Object;)V
+	public static synthetic fun removeChangeListener$default (Lhep/dataforge/properties/Property;Ljava/lang/Object;ILjava/lang/Object;)V
+}
+
+public final class hep/dataforge/properties/PropertyKt {
+	public static final fun bind (Lhep/dataforge/properties/Property;Lhep/dataforge/properties/Property;)V
+	public static final fun mirror (Lhep/dataforge/properties/Property;Lhep/dataforge/properties/Property;Lkotlinx/coroutines/CoroutineScope;)V
+	public static final fun toFlow (Lhep/dataforge/properties/Property;)Lkotlinx/coroutines/flow/StateFlow;
+}
+
+public final class hep/dataforge/provider/DfTypeKt {
+	public static final fun getDfType (Lkotlin/reflect/KClass;)Ljava/lang/String;
+}
+
+public final class hep/dataforge/provider/Path : java/lang/Iterable, kotlin/jvm/internal/markers/KMappedMarker {
+	public static final field Companion Lhep/dataforge/provider/Path$Companion;
+	public static final field PATH_SEGMENT_SEPARATOR Ljava/lang/String;
+	public static final synthetic fun box-impl (Ljava/util/List;)Lhep/dataforge/provider/Path;
+	public static fun constructor-impl (Ljava/util/List;)Ljava/util/List;
+	public fun equals (Ljava/lang/Object;)Z
+	public static fun equals-impl (Ljava/util/List;Ljava/lang/Object;)Z
+	public static final fun equals-impl0 (Ljava/util/List;Ljava/util/List;)Z
+	public static final fun getHead-impl (Ljava/util/List;)Lhep/dataforge/provider/PathToken;
+	public static final fun getLength-impl (Ljava/util/List;)I
+	public static final fun getTail-e2ET3QM (Ljava/util/List;)Ljava/util/List;
+	public final fun getTokens ()Ljava/util/List;
+	public fun hashCode ()I
+	public static fun hashCode-impl (Ljava/util/List;)I
+	public fun iterator ()Ljava/util/Iterator;
+	public static fun iterator-impl (Ljava/util/List;)Ljava/util/Iterator;
+	public fun toString ()Ljava/lang/String;
+	public static fun toString-impl (Ljava/util/List;)Ljava/lang/String;
+	public final synthetic fun unbox-impl ()Ljava/util/List;
+}
+
+public final class hep/dataforge/provider/Path$Companion {
+	public final fun parse-IN54j3k (Ljava/lang/String;)Ljava/util/List;
+}
+
+public final class hep/dataforge/provider/PathKt {
+	public static final fun plus-MQiGgVU (Ljava/util/List;Ljava/util/List;)Ljava/util/List;
+	public static final fun toPath (Lhep/dataforge/provider/PathToken;)Ljava/util/List;
+}
+
+public final class hep/dataforge/provider/PathToken {
+	public static final field Companion Lhep/dataforge/provider/PathToken$Companion;
+	public static final field TARGET_SEPARATOR Ljava/lang/String;
+	public fun <init> (Lhep/dataforge/names/Name;Ljava/lang/String;)V
+	public synthetic fun <init> (Lhep/dataforge/names/Name;Ljava/lang/String;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
+	public final fun component1 ()Lhep/dataforge/names/Name;
+	public final fun component2 ()Ljava/lang/String;
+	public final fun copy (Lhep/dataforge/names/Name;Ljava/lang/String;)Lhep/dataforge/provider/PathToken;
+	public static synthetic fun copy$default (Lhep/dataforge/provider/PathToken;Lhep/dataforge/names/Name;Ljava/lang/String;ILjava/lang/Object;)Lhep/dataforge/provider/PathToken;
+	public fun equals (Ljava/lang/Object;)Z
+	public final fun getName ()Lhep/dataforge/names/Name;
+	public final fun getTarget ()Ljava/lang/String;
+	public fun hashCode ()I
+	public fun toString ()Ljava/lang/String;
+}
+
+public final class hep/dataforge/provider/PathToken$Companion {
+	public final fun parse (Ljava/lang/String;)Lhep/dataforge/provider/PathToken;
+}
+
+public abstract interface class hep/dataforge/provider/Provider {
+	public abstract fun content (Ljava/lang/String;)Ljava/util/Map;
+	public abstract fun getDefaultChainTarget ()Ljava/lang/String;
+	public abstract fun getDefaultTarget ()Ljava/lang/String;
+}
+
+public final class hep/dataforge/provider/Provider$DefaultImpls {
+	public static fun content (Lhep/dataforge/provider/Provider;Ljava/lang/String;)Ljava/util/Map;
+	public static fun getDefaultChainTarget (Lhep/dataforge/provider/Provider;)Ljava/lang/String;
+	public static fun getDefaultTarget (Lhep/dataforge/provider/Provider;)Ljava/lang/String;
+}
+
+public final class hep/dataforge/provider/ProviderKt {
+	public static final fun provide-0Dbucg0 (Lhep/dataforge/provider/Provider;Ljava/util/List;Ljava/lang/String;)Ljava/lang/Object;
+	public static synthetic fun provide-0Dbucg0$default (Lhep/dataforge/provider/Provider;Ljava/util/List;Ljava/lang/String;ILjava/lang/Object;)Ljava/lang/Object;
+	public static final fun top (Lhep/dataforge/provider/Provider;Ljava/lang/String;Lkotlin/reflect/KClass;)Ljava/util/Map;
+}
+
+public abstract interface annotation class hep/dataforge/provider/Type : java/lang/annotation/Annotation {
+	public abstract fun id ()Ljava/lang/String;
+}
+
diff --git a/dataforge-context/build.gradle.kts b/dataforge-context/build.gradle.kts
index c5b41223..01a7e3bb 100644
--- a/dataforge-context/build.gradle.kts
+++ b/dataforge-context/build.gradle.kts
@@ -1,32 +1,30 @@
-import scientifik.useCoroutines
-
 plugins {
-    id("scientifik.mpp")
+    id("ru.mipt.npm.mpp")
+    id("ru.mipt.npm.native")
 }
 
 description = "Context and provider definitions"
 
-
-useCoroutines()
+kscience {
+    useCoroutines()
+}
 
 kotlin {
     sourceSets {
         val commonMain by getting {
             dependencies {
                 api(project(":dataforge-meta"))
-                api("io.github.microutils:kotlin-logging-common:1.7.9")
+                api("io.github.microutils:kotlin-logging:1.9.0-dev-npm-2")
             }
         }
         val jvmMain by getting {
             dependencies {
                 api(kotlin("reflect"))
-                api("io.github.microutils:kotlin-logging:1.7.9")
                 api("ch.qos.logback:logback-classic:1.2.3")
             }
         }
         val jsMain by getting {
             dependencies {
-                api("io.github.microutils:kotlin-logging-js:1.7.9")
             }
         }
     }
diff --git a/dataforge-context/src/commonMain/kotlin/hep/dataforge/context/AbstractPlugin.kt b/dataforge-context/src/commonMain/kotlin/hep/dataforge/context/AbstractPlugin.kt
index e1041935..f64c1042 100644
--- a/dataforge-context/src/commonMain/kotlin/hep/dataforge/context/AbstractPlugin.kt
+++ b/dataforge-context/src/commonMain/kotlin/hep/dataforge/context/AbstractPlugin.kt
@@ -6,7 +6,7 @@ import kotlin.properties.ReadOnlyProperty
 import kotlin.reflect.KClass
 import kotlin.reflect.KProperty
 
-abstract class AbstractPlugin(override val meta: Meta = Meta.EMPTY) : Plugin {
+public abstract class AbstractPlugin(override val meta: Meta = Meta.EMPTY) : Plugin {
     private var _context: Context? = null
     private val dependencies = ArrayList<PluginFactory<*>>()
 
@@ -30,11 +30,9 @@ abstract class AbstractPlugin(override val meta: Meta = Meta.EMPTY) : Plugin {
         dependencies.add(factory)
         return PluginDependencyDelegate(factory.type)
     }
-
-    override fun provideTop(target: String): Map<Name, Any> = emptyMap()
 }
 
-fun <T : Named> Collection<T>.toMap(): Map<Name, T> = associate { it.name to it }
+public fun <T : Named> Collection<T>.toMap(): Map<Name, T> = associate { it.name to it }
 
 private class PluginDependencyDelegate<P : Plugin>(val type: KClass<out P>) : ReadOnlyProperty<AbstractPlugin, P> {
     override fun getValue(thisRef: AbstractPlugin, property: KProperty<*>): P {
diff --git a/dataforge-context/src/commonMain/kotlin/hep/dataforge/context/Context.kt b/dataforge-context/src/commonMain/kotlin/hep/dataforge/context/Context.kt
index bf901991..605e6f8b 100644
--- a/dataforge-context/src/commonMain/kotlin/hep/dataforge/context/Context.kt
+++ b/dataforge-context/src/commonMain/kotlin/hep/dataforge/context/Context.kt
@@ -1,19 +1,18 @@
 package hep.dataforge.context
 
-import hep.dataforge.meta.*
+import hep.dataforge.meta.Laminate
+import hep.dataforge.meta.Meta
+import hep.dataforge.meta.MetaRepr
+import hep.dataforge.meta.sequence
 import hep.dataforge.names.Name
-import hep.dataforge.names.asName
 import hep.dataforge.names.plus
 import hep.dataforge.provider.Provider
-import hep.dataforge.provider.top
-import hep.dataforge.values.Value
 import kotlinx.coroutines.CoroutineScope
 import kotlinx.coroutines.Job
 import kotlinx.coroutines.SupervisorJob
 import mu.KLogger
 import mu.KotlinLogging
 import kotlin.coroutines.CoroutineContext
-import kotlin.jvm.JvmName
 
 /**
  * The local environment for anything being done in DataForge framework. Contexts are organized into tree structure with [Global] at the top.
@@ -24,73 +23,52 @@ import kotlin.jvm.JvmName
  * different plugins with the same interface in different contexts in the hierarchy. The usual behaviour is to use nearest one, but it could
  * be overridden by plugin implementation.
  *
- * Since plugins could contain mutable state, context has two states: active and inactive. No changes are allowed to active context.
- * @author Alexander Nozik
  */
-open class Context(
+public open class Context(
     final override val name: Name,
-    val parent: Context? = Global
+    public val parent: Context?,
+    meta: Meta,
+    plugins: Set<Plugin> = emptySet(),
 ) : Named, MetaRepr, Provider, CoroutineScope {
 
-    private val config = Config()
-
     /**
      * Context properties. Working as substitute for environment variables
      */
-    val properties: Meta = if (parent == null) {
-        config
+    private val properties: Laminate = if (parent == null) {
+        Laminate(meta)
     } else {
-        Laminate(config, parent.properties)
+        Laminate(meta, parent.properties)
     }
 
     /**
      * Context logger
      */
-    val logger: KLogger = KotlinLogging.logger(name.toString())
+    public val logger: KLogger = KotlinLogging.logger(name.toString())
 
     /**
      * A [PluginManager] for current context
      */
-    val plugins: PluginManager by lazy { PluginManager(this) }
+    public val plugins: PluginManager by lazy { PluginManager(this, plugins)}
 
-    private val activators = HashSet<Any>()
+    override val defaultTarget: String get() = Plugin.TARGET
 
-    /**
-     * Defines if context is used in any kind of active computations. Active context properties and plugins could not be changed
-     */
-    val isActive: Boolean = activators.isNotEmpty()
-
-    override val defaultTarget: String get() = Plugin.PLUGIN_TARGET
-
-    override fun provideTop(target: String): Map<Name, Any> {
-        return when (target) {
-            Value.TYPE -> properties.sequence().toMap()
-            Plugin.PLUGIN_TARGET -> plugins.sequence(true).associateBy { it.name }
-            else -> emptyMap()
+    public fun content(target: String, inherit: Boolean): Map<Name, Any> {
+        return if (inherit) {
+            when (target) {
+                PROPERTY_TARGET -> properties.sequence().toMap()
+                Plugin.TARGET -> plugins.list(true).associateBy { it.name }
+                else -> emptyMap()
+            }
+        } else {
+            when (target) {
+                PROPERTY_TARGET -> properties.layers.firstOrNull()?.sequence()?.toMap() ?: emptyMap()
+                Plugin.TARGET -> plugins.list(false).associateBy { it.name }
+                else -> emptyMap()
+            }
         }
     }
 
-    /**
-     * Mark context as active and used by [activator]
-     */
-    fun activate(activator: Any) {
-        activators.add(activator)
-    }
-
-    /**
-     * Mark context unused by [activator]
-     */
-    fun deactivate(activator: Any) {
-        activators.remove(activator)
-    }
-
-    /**
-     * Change the properties of the context. If active, throw an exception
-     */
-    fun configure(action: Config.() -> Unit) {
-        if (isActive) error("Can't configure active context")
-        config.action()
-    }
+    override fun content(target: String): Map<Name, Any> = content(target, true)
 
     override val coroutineContext: CoroutineContext by lazy {
         (parent ?: Global).coroutineContext.let { parenContext ->
@@ -101,81 +79,35 @@ open class Context(
     /**
      * Detach all plugins and terminate context
      */
-    open fun close() {
-        if (isActive) error("Can't close active context")
+    public open fun close() {
         //detach all plugins
         plugins.forEach { it.detach() }
     }
 
     override fun toMeta(): Meta = Meta {
         "parent" to parent?.name
-        "properties" put properties.seal()
+        "properties" put properties.layers.firstOrNull()
         "plugins" put plugins.map { it.toMeta() }
     }
-}
 
-fun Context.content(target: String): Map<Name, Any> = content<Any>(target)
-
-/**
- * A map of all objects provided by plugins with given target and type
- */
-@JvmName("typedContent")
-inline fun <reified T : Any> Context.content(target: String): Map<Name, T> =
-    plugins.flatMap { plugin ->
-        plugin.top<T>(target).entries.map { (plugin.name + it.key) to it.value }
-    }.associate { it }
-
-
-/**
- * A global root context. Closing [Global] terminates the framework.
- */
-object Global : Context("GLOBAL".asName(), null) {
-    /**
-     * Closing all contexts
-     *
-     * @throws Exception
-     */
-    override fun close() {
-        logger.info { "Shutting down GLOBAL" }
-        for (ctx in contextRegistry.values) {
-            ctx.close()
-        }
-        super.close()
+    public companion object {
+        public const val PROPERTY_TARGET: String = "context.property"
     }
-
-    private val contextRegistry = HashMap<String, Context>()
-
-    /**
-     * Get previously built context
-     *
-     * @param name
-     * @return
-     */
-    fun getContext(name: String): Context? {
-        return contextRegistry[name]
-    }
-
-    fun context(name: String, parent: Context = this, block: ContextBuilder.() -> Unit = {}): Context =
-        ContextBuilder(name, parent).apply(block).build()
-
 }
 
-
 /**
  * The interface for something that encapsulated in context
  *
- * @author Alexander Nozik
- * @version $Id: $Id
  */
-interface ContextAware {
+public interface ContextAware {
     /**
      * Get context for this object
      *
      * @return
      */
-    val context: Context
+    public val context: Context
 
-    val logger: KLogger
+    public val logger: KLogger
         get() = if (this is Named) {
             KotlinLogging.logger((context.name + this.name).toString())
         } else {
diff --git a/dataforge-context/src/commonMain/kotlin/hep/dataforge/context/ContextBuilder.kt b/dataforge-context/src/commonMain/kotlin/hep/dataforge/context/ContextBuilder.kt
index 1f267c37..b742474c 100644
--- a/dataforge-context/src/commonMain/kotlin/hep/dataforge/context/ContextBuilder.kt
+++ b/dataforge-context/src/commonMain/kotlin/hep/dataforge/context/ContextBuilder.kt
@@ -1,44 +1,44 @@
 package hep.dataforge.context
 
-import hep.dataforge.meta.DFBuilder
-import hep.dataforge.meta.Meta
-import hep.dataforge.meta.MetaBuilder
-import hep.dataforge.meta.buildMeta
+import hep.dataforge.meta.*
 import hep.dataforge.names.toName
 
 /**
  * A convenience builder for context
  */
 @DFBuilder
-class ContextBuilder(var name: String = "@anonymous", val parent: Context = Global) {
-    private val plugins = ArrayList<Plugin>()
+public class ContextBuilder(private val parent: Context = Global, public var name: String = "@anonymous") {
+    private val plugins = HashSet<Plugin>()
     private var meta = MetaBuilder()
 
-    fun properties(action: MetaBuilder.() -> Unit) {
+    public fun properties(action: MetaBuilder.() -> Unit) {
         meta.action()
     }
 
-    fun plugin(plugin: Plugin) {
+    public fun plugin(plugin: Plugin) {
         plugins.add(plugin)
     }
 
-    fun plugin(tag: PluginTag, action: MetaBuilder.() -> Unit = {}) {
-        plugins.add(PluginRepository.fetch(tag, Meta(action)))
+    @OptIn(DFExperimental::class)
+    private fun findPluginFactory(tag: PluginTag): PluginFactory<*> =
+        parent.gatherInSequence<PluginFactory<*>>(PluginFactory.TYPE).values
+            .find { it.tag.matches(tag) } ?: error("Can't resolve plugin factory for $tag")
+
+    public fun plugin(tag: PluginTag, metaBuilder: MetaBuilder.() -> Unit = {}) {
+        val factory = findPluginFactory(tag)
+        val plugin = factory.invoke(Meta(metaBuilder), parent)
+        plugins.add(plugin)
     }
 
-    fun plugin(builder: PluginFactory<*>, action: MetaBuilder.() -> Unit = {}) {
+    public fun plugin(builder: PluginFactory<*>, action: MetaBuilder.() -> Unit = {}) {
         plugins.add(builder.invoke(Meta(action)))
     }
 
-    fun plugin(name: String, group: String = "", version: String = "", action: MetaBuilder.() -> Unit = {}) {
+    public fun plugin(name: String, group: String = "", version: String = "", action: MetaBuilder.() -> Unit = {}) {
         plugin(PluginTag(name, group, version), action)
     }
 
-    fun build(): Context {
-        return Context(name.toName(), parent).apply {
-            this@ContextBuilder.plugins.forEach {
-                plugins.load(it)
-            }
-        }
+    public fun build(): Context {
+        return Context(name.toName(), parent, meta.seal(), plugins)
     }
 }
\ No newline at end of file
diff --git a/dataforge-context/src/commonMain/kotlin/hep/dataforge/context/Factory.kt b/dataforge-context/src/commonMain/kotlin/hep/dataforge/context/Factory.kt
index b01334e6..b8858a13 100644
--- a/dataforge-context/src/commonMain/kotlin/hep/dataforge/context/Factory.kt
+++ b/dataforge-context/src/commonMain/kotlin/hep/dataforge/context/Factory.kt
@@ -2,6 +2,6 @@ package hep.dataforge.context
 
 import hep.dataforge.meta.Meta
 
-interface Factory<out T : Any> {
-    operator fun invoke(meta: Meta = Meta.EMPTY, context: Context = Global): T
+public interface Factory<out T : Any> {
+    public operator fun invoke(meta: Meta = Meta.EMPTY, context: Context = Global): T
 }
\ No newline at end of file
diff --git a/dataforge-context/src/commonMain/kotlin/hep/dataforge/context/Global.kt b/dataforge-context/src/commonMain/kotlin/hep/dataforge/context/Global.kt
new file mode 100644
index 00000000..0193ca4b
--- /dev/null
+++ b/dataforge-context/src/commonMain/kotlin/hep/dataforge/context/Global.kt
@@ -0,0 +1,48 @@
+package hep.dataforge.context
+
+import hep.dataforge.meta.Meta
+import hep.dataforge.names.asName
+import kotlinx.coroutines.GlobalScope
+import kotlinx.coroutines.SupervisorJob
+import kotlin.coroutines.CoroutineContext
+import kotlin.native.concurrent.ThreadLocal
+
+/**
+ * A global root context. Closing [Global] terminates the framework.
+ */
+@ThreadLocal
+public object Global : Context("GLOBAL".asName(), null, Meta.EMPTY) {
+
+    override val coroutineContext: CoroutineContext = GlobalScope.coroutineContext + SupervisorJob()
+
+    /**
+     * Closing all contexts
+     *
+     * @throws Exception
+     */
+    override fun close() {
+        logger.info { "Shutting down GLOBAL" }
+        for (ctx in contextRegistry.values) {
+            ctx.close()
+        }
+        super.close()
+    }
+
+    private val contextRegistry = HashMap<String, Context>()
+
+    /**
+     * Get previously built context
+     *
+     * @param name
+     * @return
+     */
+    public fun getContext(name: String): Context? {
+        return contextRegistry[name]
+    }
+
+    public fun context(name: String, parent: Context = this, block: ContextBuilder.() -> Unit = {}): Context =
+        ContextBuilder(parent, name).apply(block).build().also {
+            contextRegistry[name] = it
+        }
+
+}
\ No newline at end of file
diff --git a/dataforge-context/src/commonMain/kotlin/hep/dataforge/context/Named.kt b/dataforge-context/src/commonMain/kotlin/hep/dataforge/context/Named.kt
index 9e9db17f..e32946e0 100644
--- a/dataforge-context/src/commonMain/kotlin/hep/dataforge/context/Named.kt
+++ b/dataforge-context/src/commonMain/kotlin/hep/dataforge/context/Named.kt
@@ -24,16 +24,14 @@ import hep.dataforge.names.isEmpty
  *
  * @author Alexander Nozik
  */
-interface Named {
+public interface Named {
 
     /**
      * The name of this object instance
-     *
-     * @return
      */
-    val name: Name
+    public val name: Name
 
-    companion object {
+    public companion object {
 
         /**
          * Get the name of given object. If object is Named its name is used,
@@ -42,7 +40,7 @@ interface Named {
          * @param obj
          * @return
          */
-        fun nameOf(obj: Any): Name {
+        public fun nameOf(obj: Any): Name {
             return if (obj is Named) {
                 obj.name
             } else {
@@ -56,5 +54,4 @@ interface Named {
  * Check if this object has an empty name and therefore is anonymous.
  * @return
  */
-val Named.isAnonymous: Boolean
-    get() = this.name.isEmpty()
+public val Named.isAnonymous: Boolean get() = this.name.isEmpty()
diff --git a/dataforge-context/src/commonMain/kotlin/hep/dataforge/context/Plugin.kt b/dataforge-context/src/commonMain/kotlin/hep/dataforge/context/Plugin.kt
index 6a937962..ff0e3a0c 100644
--- a/dataforge-context/src/commonMain/kotlin/hep/dataforge/context/Plugin.kt
+++ b/dataforge-context/src/commonMain/kotlin/hep/dataforge/context/Plugin.kt
@@ -1,43 +1,34 @@
 package hep.dataforge.context
 
+import hep.dataforge.context.Plugin.Companion.TARGET
 import hep.dataforge.meta.Meta
 import hep.dataforge.meta.MetaRepr
-import hep.dataforge.meta.buildMeta
 import hep.dataforge.names.Name
 import hep.dataforge.names.toName
 import hep.dataforge.provider.Provider
+import hep.dataforge.provider.Type
 
 /**
  * The interface to define a Context plugin. A plugin stores all runtime features of a context.
  * The plugin is by default configurable and a Provider (both features could be ignored).
  * The plugin must in most cases have an empty constructor in order to be able to load it from library.
  *
- *
  * The plugin lifecycle is the following:
  *
- *
  * create - configure - attach - detach - destroy
- *
- *
- * Configuration of attached plugin is possible for a context which is not in a runtime mode, but it is not recommended.
- *
- * @author Alexander Nozik
  */
-interface Plugin : Named, ContextAware, Provider, MetaRepr {
+@Type(TARGET)
+public interface Plugin : Named, ContextAware, Provider, MetaRepr {
 
     /**
      * Get tag for this plugin
-     *
-     * @return
      */
-    val tag: PluginTag
+    public val tag: PluginTag
 
-    val meta: Meta
+    public val meta: Meta
 
     /**
      * The name of this plugin ignoring version and group
-     *
-     * @return
      */
     override val name: Name get() = tag.name.toName()
 
@@ -45,25 +36,21 @@ interface Plugin : Named, ContextAware, Provider, MetaRepr {
      * Plugin dependencies which are required to attach this plugin. Plugin
      * dependencies must be initialized and enabled in the Context before this
      * plugin is enabled.
-     *
-     * @return
      */
-    fun dependsOn(): Collection<PluginFactory<*>>
+    public fun dependsOn(): Collection<PluginFactory<*>>
 
     /**
      * Start this plugin and attach registration info to the context. This method
      * should be called only via PluginManager to avoid dependency issues.
-     *
-     * @param context
      */
-    fun attach(context: Context)
+    public fun attach(context: Context)
 
     /**
      * Stop this plugin and remove registration info from context and other
      * plugins. This method should be called only via PluginManager to avoid
      * dependency issues.
      */
-    fun detach()
+    public fun detach()
 
     override fun toMeta(): Meta = Meta {
         "context" put context.name.toString()
@@ -72,9 +59,8 @@ interface Plugin : Named, ContextAware, Provider, MetaRepr {
         "meta" put meta
     }
 
-    companion object {
-
-        const val PLUGIN_TARGET = "plugin"
+    public companion object {
+        public const val TARGET: String = "plugin"
     }
 
 }
\ No newline at end of file
diff --git a/dataforge-context/src/commonMain/kotlin/hep/dataforge/context/PluginManager.kt b/dataforge-context/src/commonMain/kotlin/hep/dataforge/context/PluginManager.kt
index e6e8464e..3e9def85 100644
--- a/dataforge-context/src/commonMain/kotlin/hep/dataforge/context/PluginManager.kt
+++ b/dataforge-context/src/commonMain/kotlin/hep/dataforge/context/PluginManager.kt
@@ -2,42 +2,62 @@ package hep.dataforge.context
 
 import hep.dataforge.meta.Meta
 import hep.dataforge.meta.MetaBuilder
+import hep.dataforge.provider.Type
 import kotlin.reflect.KClass
 
+
+@Type(PluginFactory.TYPE)
+public interface PluginFactory<T : Plugin> : Factory<T> {
+    public val tag: PluginTag
+    public val type: KClass<out T>
+
+    public companion object {
+        public const val TYPE: String = "pluginFactory"
+    }
+}
+
 /**
  * The manager for plugin system. Should monitor plugin dependencies and locks.
  *
  * @property context A context for this plugin manager
  * @author Alexander Nozik
  */
-class PluginManager(override val context: Context) : ContextAware, Iterable<Plugin> {
+public class PluginManager(override val context: Context, plugins: Set<Plugin>) : ContextAware, Iterable<Plugin> {
+
+    //TODO refactor to read-only container
 
     /**
      * A set of loaded plugins
      */
-    private val plugins = HashSet<Plugin>()
+    private val plugins: HashSet<Plugin> = HashSet(plugins)
+
+    init {
+        plugins.forEach { it.attach(context) }
+    }
 
     /**
      * A [PluginManager] of parent context if it is present
      */
     private val parent: PluginManager? = context.parent?.plugins
 
-
-    fun sequence(recursive: Boolean): Sequence<Plugin> {
-        return if (recursive && parent != null) {
-            plugins.asSequence() + parent.sequence(true)
+    /**
+     * List plugins stored in this [PluginManager]. If [inherit] is true, include parent plugins as well
+     */
+    public fun list(inherit: Boolean): Collection<Plugin> {
+        return if (inherit && parent != null) {
+            plugins + parent.list(true)
         } else {
-            plugins.asSequence()
+            plugins
         }
     }
 
     /**
      * Get existing plugin or return null if not present. Only first matching plugin is returned.
-     * @param recursive search for parent [PluginManager] plugins
+     * @param inherit search for parent [PluginManager] plugins
      * @param predicate condition for the plugin
      */
-    fun find(recursive: Boolean = true, predicate: (Plugin) -> Boolean): Plugin? = sequence(recursive).find(predicate)
-
+    public fun find(inherit: Boolean = true, predicate: (Plugin) -> Boolean): Plugin? =
+        list(inherit).find(predicate)
 
     /**
      * Find a loaded plugin via its tag
@@ -45,8 +65,8 @@ class PluginManager(override val context: Context) : ContextAware, Iterable<Plug
      * @param tag
      * @return
      */
-    operator fun get(tag: PluginTag, recursive: Boolean = true): Plugin? = find(recursive) { tag.matches(it.tag) }
-
+    public operator fun get(tag: PluginTag, inherit: Boolean = true): Plugin? =
+        find(inherit) { tag.matches(it.tag) }
 
     /**
      * Find a loaded plugin via its class. This method does not check if the result is unique and just returns first
@@ -60,13 +80,13 @@ class PluginManager(override val context: Context) : ContextAware, Iterable<Plug
      * @return
      */
     @Suppress("UNCHECKED_CAST")
-    operator fun <T : Any> get(type: KClass<out T>, tag: PluginTag? = null, recursive: Boolean = true): T? =
+    public operator fun <T : Any> get(type: KClass<out T>, tag: PluginTag? = null, recursive: Boolean = true): T? =
         find(recursive) { type.isInstance(it) && (tag == null || tag.matches(it.tag)) } as T?
 
-    inline operator fun <reified T : Any> get(tag: PluginTag? = null, recursive: Boolean = true): T? =
+    public inline operator fun <reified T : Any> get(tag: PluginTag? = null, recursive: Boolean = true): T? =
         get(T::class, tag, recursive)
 
-    inline operator fun <reified T : Plugin> get(factory: PluginFactory<T>, recursive: Boolean = true): T? =
+    public inline operator fun <reified T : Plugin> get(factory: PluginFactory<T>, recursive: Boolean = true): T? =
         get(factory.type, factory.tag, recursive)
 
     /**
@@ -76,11 +96,9 @@ class PluginManager(override val context: Context) : ContextAware, Iterable<Plug
      * @param plugin
      * @return
      */
-    fun <T : Plugin> load(plugin: T): T {
-        if (context.isActive) error("Can't load plugin into active context")
-
+    public fun <T : Plugin> load(plugin: T): T {
         if (get(plugin::class, plugin.tag, recursive = false) != null) {
-            error("Plugin of type ${plugin::class} already exists in ${context.name}")
+            error("Plugin with tag ${plugin.tag} already exists in ${context.name}")
         } else {
             for (tag in plugin.dependsOn()) {
                 fetch(tag, true)
@@ -96,18 +114,16 @@ class PluginManager(override val context: Context) : ContextAware, Iterable<Plug
     /**
      * Load a plugin using its factory
      */
-    fun <T : Plugin> load(factory: PluginFactory<T>, meta: Meta = Meta.EMPTY): T =
+    public fun <T : Plugin> load(factory: PluginFactory<T>, meta: Meta = Meta.EMPTY): T =
         load(factory(meta, context))
 
-    fun <T : Plugin> load(factory: PluginFactory<T>, metaBuilder: MetaBuilder.() -> Unit): T =
+    public fun <T : Plugin> load(factory: PluginFactory<T>, metaBuilder: MetaBuilder.() -> Unit): T =
         load(factory, Meta(metaBuilder))
 
     /**
      * Remove a plugin from [PluginManager]
      */
-    fun remove(plugin: Plugin) {
-        if (context.isActive) error("Can't remove plugin from active context")
-
+    public fun remove(plugin: Plugin) {
         if (plugins.contains(plugin)) {
             logger.info { "Removing plugin ${plugin.name} from ${context.name}" }
             plugin.detach()
@@ -117,9 +133,8 @@ class PluginManager(override val context: Context) : ContextAware, Iterable<Plug
 
     /**
      * Get an existing plugin with given meta or load new one using provided factory
-     *
      */
-    fun <T : Plugin> fetch(factory: PluginFactory<T>, recursive: Boolean = true, meta: Meta = Meta.EMPTY): T {
+    public fun <T : Plugin> fetch(factory: PluginFactory<T>, recursive: Boolean = true, meta: Meta = Meta.EMPTY): T {
         val loaded = get(factory.type, factory.tag, recursive)
         return when {
             loaded == null -> load(factory(meta, context))
@@ -128,10 +143,10 @@ class PluginManager(override val context: Context) : ContextAware, Iterable<Plug
         }
     }
 
-    fun <T : Plugin> fetch(
+    public fun <T : Plugin> fetch(
         factory: PluginFactory<T>,
         recursive: Boolean = true,
-        metaBuilder: MetaBuilder.() -> Unit
+        metaBuilder: MetaBuilder.() -> Unit,
     ): T = fetch(factory, recursive, Meta(metaBuilder))
 
     override fun iterator(): Iterator<Plugin> = plugins.iterator()
diff --git a/dataforge-context/src/commonMain/kotlin/hep/dataforge/context/PluginRepository.kt b/dataforge-context/src/commonMain/kotlin/hep/dataforge/context/PluginRepository.kt
deleted file mode 100644
index 248b239c..00000000
--- a/dataforge-context/src/commonMain/kotlin/hep/dataforge/context/PluginRepository.kt
+++ /dev/null
@@ -1,48 +0,0 @@
-package hep.dataforge.context
-
-import hep.dataforge.meta.Meta
-import kotlin.reflect.KClass
-
-interface PluginFactory<T : Plugin> : Factory<T> {
-    val tag: PluginTag
-    val type: KClass<out T>
-}
-
-expect object PluginRepository {
-
-    fun register(factory: PluginFactory<*>)
-
-    /**
-     * List plugins available in the repository
-     */
-    fun list(): Sequence<PluginFactory<*>>
-
-}
-
-/**
- * Fetch specific plugin and instantiate it with given meta
- */
-fun PluginRepository.fetch(tag: PluginTag, meta: Meta = Meta.EMPTY): Plugin =
-    list().find { it.tag.matches(tag) }?.invoke(meta = meta)
-        ?: error("Plugin with tag $tag not found in the repository")
-
-fun <T : Plugin> PluginRepository.register(
-    tag: PluginTag,
-    type: KClass<out T>,
-    constructor: (Context, Meta) -> T
-): PluginFactory<T> {
-    val factory = object : PluginFactory<T> {
-        override val tag: PluginTag = tag
-        override val type: KClass<out T> = type
-
-        override fun invoke(meta: Meta, context: Context): T = constructor(context, meta)
-
-    }
-    register(factory)
-    return factory
-}
-
-inline fun <reified T : Plugin> PluginRepository.register(tag: PluginTag, noinline constructor: (Context, Meta) -> T) =
-    register(tag, T::class, constructor)
-
-fun PluginRepository.register(plugin: Plugin) = register(plugin.tag, plugin::class) { _, _ -> plugin }
\ No newline at end of file
diff --git a/dataforge-context/src/commonMain/kotlin/hep/dataforge/context/PluginTag.kt b/dataforge-context/src/commonMain/kotlin/hep/dataforge/context/PluginTag.kt
index f02308fd..1cd39929 100644
--- a/dataforge-context/src/commonMain/kotlin/hep/dataforge/context/PluginTag.kt
+++ b/dataforge-context/src/commonMain/kotlin/hep/dataforge/context/PluginTag.kt
@@ -2,7 +2,6 @@ package hep.dataforge.context
 
 import hep.dataforge.meta.Meta
 import hep.dataforge.meta.MetaRepr
-import hep.dataforge.meta.buildMeta
 
 /**
  * The tag which contains information about name, group and version of some
@@ -10,7 +9,7 @@ import hep.dataforge.meta.buildMeta
  *
  * @author Alexander Nozik
  */
-data class PluginTag(
+public data class PluginTag(
     val name: String,
     val group: String = "",
     val version: String = ""
@@ -22,7 +21,7 @@ data class PluginTag(
      * @param otherTag
      * @return
      */
-    fun matches(otherTag: PluginTag): Boolean {
+    public fun matches(otherTag: PluginTag): Boolean {
         return matchesName(otherTag) && matchesGroup(otherTag)
     }
 
@@ -42,9 +41,9 @@ data class PluginTag(
         "version" put version
     }
 
-    companion object {
+    public companion object {
 
-        const val DATAFORGE_GROUP = "hep.dataforge"
+        public const val DATAFORGE_GROUP: String = "hep.dataforge"
 
         /**
          * Build new PluginTag from standard string representation
@@ -52,7 +51,7 @@ data class PluginTag(
          * @param tag
          * @return
          */
-        fun fromString(tag: String): PluginTag {
+        public fun fromString(tag: String): PluginTag {
             val sepIndex = tag.indexOf(":")
             return if (sepIndex >= 0) {
                 PluginTag(group = tag.substring(0, sepIndex), name = tag.substring(sepIndex + 1))
diff --git a/dataforge-context/src/commonMain/kotlin/hep/dataforge/context/resolve.kt b/dataforge-context/src/commonMain/kotlin/hep/dataforge/context/resolve.kt
new file mode 100644
index 00000000..811220af
--- /dev/null
+++ b/dataforge-context/src/commonMain/kotlin/hep/dataforge/context/resolve.kt
@@ -0,0 +1,96 @@
+package hep.dataforge.context
+
+import hep.dataforge.meta.DFExperimental
+import hep.dataforge.names.Name
+import hep.dataforge.names.plus
+import hep.dataforge.provider.Provider
+import hep.dataforge.provider.top
+import kotlin.reflect.KClass
+import kotlin.reflect.cast
+
+/**
+ * Resolve a specific element in top level elements of the provider and attempt to cast it to the given type
+ */
+private fun <T : Any> Provider.provide(target: String, name: Name, type: KClass<out T>): T? {
+    return content(target)[name]?.let { type.cast(it) }
+}
+
+/**
+ * Resolve a top level object with given [target] and [name] in a [Context] own scope or its plugins.
+ */
+public fun <T : Any> Context.resolve(target: String, name: Name, type: KClass<out T>): T? {
+    //Try searching for plugin an context property
+    provide(target, name, type)?.let { return it }
+    val pluginContent = plugins.mapNotNull { it.provide(target, name, type) }
+    return if (pluginContent.isEmpty()) {
+        parent?.resolve<T>(target, name, type)
+    } else {
+        pluginContent.single() // throws error in case of name/type conflicts
+    }
+}
+
+/**
+ * Resolve a top level object with given [target] and [name] in a [Context] own scope or its plugins.
+ */
+public inline fun <reified T : Any> Context.resolve(target: String, name: Name): T? =
+    resolve(target, name, T::class)
+
+/**
+ * Gather a map of all top-level objects with given [target] from context plugins.
+ * Content from plugins is prefixed by plugin name so name conflicts are impossible
+ * This operation could be slow in case of large number of plugins
+ */
+public fun <T : Any> Context.gather(
+    target: String,
+    type: KClass<out T>,
+    inherit: Boolean = true,
+): Map<Name, T> = buildMap {
+    putAll(top(target, type))
+    plugins.forEach { plugin ->
+        plugin.top(target, type).forEach { (name, value) ->
+            if (containsKey(name)) error("Name conflict during gather. An item with name $name could not be gathered from $plugin because key is already present.")
+            put(plugin.name + name, value)
+        }
+    }
+    if (inherit) {
+        parent?.gather(target, type, inherit)?.forEach {
+            //put all values from parent if they are not conflicting
+            if (!containsKey(it.key)) {
+                put(it.key, it.value)
+            }
+        }
+    }
+}
+
+public inline fun <reified T : Any> Context.gather(target: String, inherit: Boolean = true): Map<Name, T> =
+    gather(target, T::class, inherit)
+
+/**
+ * Gather all content from context itself and its plugins in a form of sequence of name-value pairs. Ignores name conflicts.
+ *
+ * Adds parent context sequence as well if [inherit] is true
+ */
+@DFExperimental
+public fun <T : Any> Context.gatherInSequence(
+    target: String,
+    type: KClass<out T>,
+    inherit: Boolean = true,
+): Sequence<Map.Entry<Name, T>> = sequence {
+    yieldAll(top(target, type).entries)
+    plugins.forEach { plugin ->
+        yieldAll(plugin.top(target, type).mapKeys { plugin.name + it.key }.entries)
+    }
+    if (inherit) {
+        parent?.gather(target, type, inherit)?.let {
+            yieldAll(it.entries)
+        }
+    }
+}
+
+@DFExperimental
+public inline fun <reified T : Any> Context.gatherInSequence(
+    target: String,
+    inherit: Boolean = true,
+): Sequence<Map.Entry<Name, T>> = gatherInSequence(target, T::class, inherit)
+
+public val <T> Sequence<Map.Entry<Name, T>>.values: Sequence<T> get() = map { it.value }
\ No newline at end of file
diff --git a/dataforge-context/src/commonMain/kotlin/hep/dataforge/properties/ConfigProperty.kt b/dataforge-context/src/commonMain/kotlin/hep/dataforge/properties/ConfigProperty.kt
new file mode 100644
index 00000000..329662b5
--- /dev/null
+++ b/dataforge-context/src/commonMain/kotlin/hep/dataforge/properties/ConfigProperty.kt
@@ -0,0 +1,33 @@
+package hep.dataforge.properties
+
+import hep.dataforge.meta.Config
+import hep.dataforge.meta.DFExperimental
+import hep.dataforge.meta.get
+import hep.dataforge.meta.transformations.MetaConverter
+import hep.dataforge.meta.transformations.nullableItemToObject
+import hep.dataforge.meta.transformations.nullableObjectToMetaItem
+import hep.dataforge.names.Name
+
+@DFExperimental
+public class ConfigProperty<T : Any>(
+    public val config: Config,
+    public val name: Name,
+    public val converter: MetaConverter<T>,
+) : Property<T?> {
+
+    override var value: T?
+        get() = converter.nullableItemToObject(config[name])
+        set(value) {
+            config.setItem(name,converter.nullableObjectToMetaItem(value))
+        }
+
+    override fun onChange(owner: Any?, callback: (T?) -> Unit) {
+        config.onChange(owner) { name, oldItem, newItem ->
+            if (name == this.name && oldItem != newItem) callback(converter.nullableItemToObject(newItem))
+        }
+    }
+
+    override fun removeChangeListener(owner: Any?) {
+        config.removeListener(owner)
+    }
+}
\ No newline at end of file
diff --git a/dataforge-context/src/commonMain/kotlin/hep/dataforge/properties/Property.kt b/dataforge-context/src/commonMain/kotlin/hep/dataforge/properties/Property.kt
new file mode 100644
index 00000000..987cfe4c
--- /dev/null
+++ b/dataforge-context/src/commonMain/kotlin/hep/dataforge/properties/Property.kt
@@ -0,0 +1,48 @@
+package hep.dataforge.properties
+
+import hep.dataforge.meta.DFExperimental
+import kotlinx.coroutines.CoroutineScope
+import kotlinx.coroutines.ExperimentalCoroutinesApi
+import kotlinx.coroutines.flow.MutableStateFlow
+import kotlinx.coroutines.flow.StateFlow
+
+@DFExperimental
+public interface Property<T> {
+    public var value: T
+
+    public fun onChange(owner: Any? = null, callback: (T) -> Unit)
+    public fun removeChangeListener(owner: Any? = null)
+}
+
+@DFExperimental
+@OptIn(ExperimentalCoroutinesApi::class)
+public fun <T> Property<T>.toFlow(): StateFlow<T> = MutableStateFlow(value).also { stateFlow ->
+    onChange {
+        stateFlow.value = it
+    }
+}
+
+/**
+ * Reflect all changes in the [source] property onto this property
+ *
+ * @return a mirroring job
+ */
+@DFExperimental
+public fun <T> Property<T>.mirror(source: Property<T>, scope: CoroutineScope) {
+    source.onChange(this) {
+        this.value = it
+    }
+}
+
+/**
+ * Bi-directional connection between properties
+ */
+@DFExperimental
+public fun <T> Property<T>.bind(other: Property<T>) {
+    onChange(other) {
+        other.value = it
+    }
+    other.onChange {
+        this.value = it
+    }
+}
\ No newline at end of file
diff --git a/dataforge-context/src/commonMain/kotlin/hep/dataforge/provider/Path.kt b/dataforge-context/src/commonMain/kotlin/hep/dataforge/provider/Path.kt
index 06c36ab0..6cd0d7fa 100644
--- a/dataforge-context/src/commonMain/kotlin/hep/dataforge/provider/Path.kt
+++ b/dataforge-context/src/commonMain/kotlin/hep/dataforge/provider/Path.kt
@@ -26,25 +26,25 @@ import hep.dataforge.names.toName
  * @author Alexander Nozik
  * @version $Id: $Id
  */
-inline class Path(val tokens: List<PathToken>) : Iterable<PathToken> {
+public inline class Path(public val tokens: List<PathToken>) : Iterable<PathToken> {
 
-    val head: PathToken? get() = tokens.firstOrNull()
+    public val head: PathToken? get() = tokens.firstOrNull()
 
-    val length: Int get() = tokens.size
+    public val length: Int get() = tokens.size
 
     /**
      * Returns non-empty optional containing the chain without first segment in case of chain path.
      *
      * @return
      */
-    val tail: Path? get() = if (tokens.isEmpty()) null else Path(tokens.drop(1))
+    public val tail: Path? get() = if (tokens.isEmpty()) null else Path(tokens.drop(1))
 
     override fun iterator(): Iterator<PathToken> = tokens.iterator()
 
-    companion object {
-        const val PATH_SEGMENT_SEPARATOR = "/"
+    public companion object {
+        public const val PATH_SEGMENT_SEPARATOR: String = "/"
 
-        fun parse(path: String): Path {
+        public fun parse(path: String): Path {
             val head = path.substringBefore(PATH_SEGMENT_SEPARATOR)
             val tail = path.substringAfter(PATH_SEGMENT_SEPARATOR)
             return PathToken.parse(head).toPath() + parse(tail)
@@ -52,18 +52,18 @@ inline class Path(val tokens: List<PathToken>) : Iterable<PathToken> {
     }
 }
 
-operator fun Path.plus(path: Path) = Path(this.tokens + path.tokens)
+public operator fun Path.plus(path: Path): Path = Path(this.tokens + path.tokens)
 
-data class PathToken(val name: Name, val target: String? = null) {
+public data class PathToken(val name: Name, val target: String? = null) {
     override fun toString(): String = if (target == null) {
         name.toString()
     } else {
         "$target$TARGET_SEPARATOR$name"
     }
 
-    companion object {
-        const val TARGET_SEPARATOR = "::"
-        fun parse(token: String): PathToken {
+    public companion object {
+        public const val TARGET_SEPARATOR: String = "::"
+        public fun parse(token: String): PathToken {
             val target = token.substringBefore(TARGET_SEPARATOR, "")
             val name = token.substringAfter(TARGET_SEPARATOR).toName()
             if (target.contains("[")) TODO("target separators in queries are not supported")
@@ -72,4 +72,4 @@ data class PathToken(val name: Name, val target: String? = null) {
     }
 }
 
-fun PathToken.toPath() = Path(listOf(this))
+public fun PathToken.toPath(): Path = Path(listOf(this))
diff --git a/dataforge-context/src/commonMain/kotlin/hep/dataforge/provider/Provider.kt b/dataforge-context/src/commonMain/kotlin/hep/dataforge/provider/Provider.kt
index b1d769e2..3a153d86 100644
--- a/dataforge-context/src/commonMain/kotlin/hep/dataforge/provider/Provider.kt
+++ b/dataforge-context/src/commonMain/kotlin/hep/dataforge/provider/Provider.kt
@@ -16,41 +16,37 @@
 package hep.dataforge.provider
 
 import hep.dataforge.names.Name
-import hep.dataforge.names.toName
+import kotlin.reflect.KClass
+import kotlin.reflect.safeCast
 
 /**
  * A marker utility interface for providers.
  *
  * @author Alexander Nozik
  */
-interface Provider {
+public interface Provider {
 
     /**
      * Default target for this provider
-     *
-     * @return
      */
-    val defaultTarget: String get() = ""
+    public val defaultTarget: String get() = ""
 
     /**
      * Default target for next chain segment
-     *
-     * @return
      */
-    val defaultChainTarget: String get() = ""
-
+    public val defaultChainTarget: String get() = ""
 
     /**
      * A map of direct children for specific target
      */
-    fun provideTop(target: String): Map<Name, Any>
+    public fun content(target: String): Map<Name, Any> = emptyMap()
 }
 
-fun Provider.provide(path: Path, targetOverride: String? = null): Any? {
+public fun Provider.provide(path: Path, targetOverride: String? = null): Any? {
     if (path.length == 0) throw IllegalArgumentException("Can't provide by empty path")
     val first = path.first()
     val target = targetOverride ?: first.target ?: defaultTarget
-    val res = provideTop(target)[first.name] ?: return null
+    val res = content(target)[first.name] ?: return null
     return when (path.length) {
         1 -> res
         else -> {
@@ -65,24 +61,29 @@ fun Provider.provide(path: Path, targetOverride: String? = null): Any? {
 /**
  * Type checked provide
  */
-inline fun <reified T : Any> Provider.provide(path: String): T? {
-    return provide(Path.parse(path)) as? T
+public inline fun <reified T : Any> Provider.provide(path: String, targetOverride: String? = null): T? {
+    return provide(Path.parse(path), targetOverride) as? T
 }
+//
+//inline fun <reified T : Any> Provider.provide(target: String, name: Name): T? {
+//    return provide(PathToken(name, target).toPath()) as? T
+//}
 
-inline fun <reified T : Any> Provider.provide(target: String, name: Name): T? {
-    return provide(PathToken(name, target).toPath()) as? T
-}
-
-inline fun <reified T : Any> Provider.provide(target: String, name: String): T? =
-    provide(target, name.toName())
+//inline fun <reified T : Any> Provider.provide(target: String, name: String): T? =
+//    provide(target, name.toName())
 
 /**
  *  Typed top level content
  */
-inline fun <reified T : Any> Provider.top(target: String): Map<Name, T> {
-    return provideTop(target).mapValues {
-        it.value as? T ?: error("The type of element $it is ${it::class} but ${T::class} is expected")
+public fun <T : Any> Provider.top(target: String, type: KClass<out T>): Map<Name, T> {
+    return content(target).mapValues {
+        type.safeCast(it.value) ?: error("The type of element $it is ${it::class} but $type is expected")
     }
 }
 
+/**
+ *  Typed top level content
+ */
+public inline fun <reified T : Any> Provider.top(target: String): Map<Name, T> = top(target, T::class)
+
 
diff --git a/dataforge-context/src/commonMain/kotlin/hep/dataforge/provider/Type.kt b/dataforge-context/src/commonMain/kotlin/hep/dataforge/provider/Type.kt
index a31f1fdb..e07cfd10 100644
--- a/dataforge-context/src/commonMain/kotlin/hep/dataforge/provider/Type.kt
+++ b/dataforge-context/src/commonMain/kotlin/hep/dataforge/provider/Type.kt
@@ -7,4 +7,4 @@ package hep.dataforge.provider
  */
 @MustBeDocumented
 @Target(AnnotationTarget.CLASS)
-annotation class Type(val id: String)
+public annotation class Type(val id: String)
diff --git a/dataforge-context/src/commonTest/kotlin/hep/dataforge/context/ContextTest.kt b/dataforge-context/src/commonTest/kotlin/hep/dataforge/context/ContextTest.kt
index 584e500c..58647400 100644
--- a/dataforge-context/src/commonTest/kotlin/hep/dataforge/context/ContextTest.kt
+++ b/dataforge-context/src/commonTest/kotlin/hep/dataforge/context/ContextTest.kt
@@ -11,7 +11,7 @@ class ContextTest {
     class DummyPlugin : AbstractPlugin() {
         override val tag get() = PluginTag("test")
 
-        override fun provideTop(target: String): Map<Name, Any> {
+        override fun content(target: String): Map<Name, Any> {
             return when(target){
                 "test" -> listOf("a", "b", "c.d").associate { it.toName() to it.toName() }
                 else -> emptyMap()
@@ -21,8 +21,11 @@ class ContextTest {
 
     @Test
     fun testPluginManager() {
-        Global.plugins.load(DummyPlugin())
-        val members = Global.content<Name>("test")
+        val context = Global.context("test"){
+            plugin(DummyPlugin())
+        }
+        //Global.plugins.load(DummyPlugin())
+        val members = context.gather<Name>("test")
         assertEquals(3, members.count())
         members.forEach {
             assertEquals(it.key, it.value.appendLeft("test"))
diff --git a/dataforge-context/src/jsMain/kotlin/hep/dataforge/context/PluginRepository.kt b/dataforge-context/src/jsMain/kotlin/hep/dataforge/context/PluginRepository.kt
deleted file mode 100644
index 78a2952e..00000000
--- a/dataforge-context/src/jsMain/kotlin/hep/dataforge/context/PluginRepository.kt
+++ /dev/null
@@ -1,16 +0,0 @@
-package hep.dataforge.context
-
-
-actual object PluginRepository {
-
-    private val factories: MutableSet<PluginFactory<*>> = HashSet()
-
-    actual fun register(factory: PluginFactory<*>) {
-        factories.add(factory)
-    }
-
-    /**
-     * List plugins available in the repository
-     */
-    actual fun list(): Sequence<PluginFactory<*>> = factories.asSequence()
-}
\ No newline at end of file
diff --git a/dataforge-context/src/jsMain/kotlin/hep/dataforge/properties/bindings.kt b/dataforge-context/src/jsMain/kotlin/hep/dataforge/properties/bindings.kt
new file mode 100644
index 00000000..05818cae
--- /dev/null
+++ b/dataforge-context/src/jsMain/kotlin/hep/dataforge/properties/bindings.kt
@@ -0,0 +1,32 @@
+package hep.dataforge.properties
+
+import hep.dataforge.meta.DFExperimental
+import org.w3c.dom.HTMLInputElement
+
+@DFExperimental
+fun HTMLInputElement.bindValue(property: Property<String>) {
+    if (this.onchange != null) error("Input element already bound")
+    this.onchange = {
+        property.value = this.value
+        Unit
+    }
+    property.onChange(this) {
+        if (value != it) {
+            value = it
+        }
+    }
+}
+
+@DFExperimental
+fun HTMLInputElement.bindChecked(property: Property<Boolean>) {
+    if (this.onchange != null) error("Input element already bound")
+    this.onchange = {
+        property.value = this.checked
+        Unit
+    }
+    property.onChange(this) {
+        if (checked != it) {
+            checked = it
+        }
+    }
+}
\ No newline at end of file
diff --git a/dataforge-context/src/jvmMain/kotlin/hep/dataforge/context/ClassLoaderPlugin.kt b/dataforge-context/src/jvmMain/kotlin/hep/dataforge/context/ClassLoaderPlugin.kt
index 6d401613..a1e0e6e6 100644
--- a/dataforge-context/src/jvmMain/kotlin/hep/dataforge/context/ClassLoaderPlugin.kt
+++ b/dataforge-context/src/jvmMain/kotlin/hep/dataforge/context/ClassLoaderPlugin.kt
@@ -19,24 +19,24 @@ import java.util.*
 import kotlin.reflect.KClass
 import kotlin.reflect.full.cast
 
-class ClassLoaderPlugin(val classLoader: ClassLoader) : AbstractPlugin() {
+public class ClassLoaderPlugin(private val classLoader: ClassLoader) : AbstractPlugin() {
     override val tag: PluginTag = PluginTag("classLoader", PluginTag.DATAFORGE_GROUP)
 
     private val serviceCache: MutableMap<Class<*>, ServiceLoader<*>> = HashMap()
 
-    fun <T : Any> services(type: KClass<T>): Sequence<T> {
+    public fun <T : Any> services(type: KClass<T>): Sequence<T> {
         return serviceCache.getOrPut(type.java) { ServiceLoader.load(type.java, classLoader) }.asSequence()
             .map { type.cast(it) }
     }
 
-    companion object {
-        val DEFAULT = ClassLoaderPlugin(Global::class.java.classLoader)
+    public companion object {
+        public val DEFAULT: ClassLoaderPlugin = ClassLoaderPlugin(Global::class.java.classLoader)
     }
 }
 
-val Context.classLoaderPlugin get() = this.plugins.get() ?: ClassLoaderPlugin.DEFAULT
+public val Context.classLoaderPlugin: ClassLoaderPlugin get() = this.plugins.get() ?: ClassLoaderPlugin.DEFAULT
 
-inline fun <reified T : Any> Context.services() = classLoaderPlugin.services(T::class)
+public inline fun <reified T : Any> Context.services(): Sequence<T> = classLoaderPlugin.services(T::class)
 
 
 //open class JVMContext(
diff --git a/dataforge-context/src/jvmMain/kotlin/hep/dataforge/context/PluginRepository.kt b/dataforge-context/src/jvmMain/kotlin/hep/dataforge/context/PluginRepository.kt
deleted file mode 100644
index 83455fd6..00000000
--- a/dataforge-context/src/jvmMain/kotlin/hep/dataforge/context/PluginRepository.kt
+++ /dev/null
@@ -1,17 +0,0 @@
-package hep.dataforge.context
-
-actual object PluginRepository {
-
-    private val factories: MutableSet<PluginFactory<*>> = HashSet()
-
-    actual fun register(factory: PluginFactory<*>) {
-        factories.add(factory)
-    }
-
-    /**
-     * List plugins available in the repository
-     */
-    actual fun list(): Sequence<PluginFactory<*>> =
-        factories.asSequence() + Global.services()
-
-}
\ No newline at end of file
diff --git a/dataforge-context/src/jvmMain/kotlin/hep/dataforge/provider/Types.kt b/dataforge-context/src/jvmMain/kotlin/hep/dataforge/provider/Types.kt
deleted file mode 100644
index dfe81ce0..00000000
--- a/dataforge-context/src/jvmMain/kotlin/hep/dataforge/provider/Types.kt
+++ /dev/null
@@ -1,44 +0,0 @@
-package hep.dataforge.provider
-
-import hep.dataforge.context.Context
-import hep.dataforge.context.content
-import hep.dataforge.names.Name
-import kotlin.reflect.KClass
-import kotlin.reflect.full.findAnnotation
-
-/**
- *
- */
-object Types {
-    operator fun get(cl: KClass<*>): String {
-        return cl.findAnnotation<Type>()?.id ?: cl.simpleName ?: ""
-    }
-
-    operator fun get(obj: Any): String {
-        return get(obj::class)
-    }
-}
-
-/**
- * Provide an object with given name inferring target from its type using [Type] annotation
- */
-inline fun <reified T : Any> Provider.provideByType(name: String): T? {
-    val target = Types[T::class]
-    return provide(target, name)
-}
-
-inline fun <reified T : Any> Provider.provideByType(name: Name): T? {
-    val target = Types[T::class]
-    return provide(target, name)
-}
-
-inline fun <reified T : Any> Provider.top(): Map<Name, T> {
-    val target = Types[T::class]
-    return top(target)
-}
-
-/**
- * A sequences of all objects provided by plugins with given target and type
- */
-inline fun <reified T : Any> Context.content(): Map<Name, T> = content<T>(Types[T::class])
-
diff --git a/dataforge-context/src/jvmMain/kotlin/hep/dataforge/provider/dfType.kt b/dataforge-context/src/jvmMain/kotlin/hep/dataforge/provider/dfType.kt
new file mode 100644
index 00000000..9c08d6a8
--- /dev/null
+++ b/dataforge-context/src/jvmMain/kotlin/hep/dataforge/provider/dfType.kt
@@ -0,0 +1,36 @@
+package hep.dataforge.provider
+
+import hep.dataforge.context.Context
+import hep.dataforge.context.gather
+import hep.dataforge.meta.DFExperimental
+import hep.dataforge.names.Name
+import kotlin.reflect.KClass
+import kotlin.reflect.full.findAnnotation
+
+
+@DFExperimental
+public val KClass<*>.dfType: String
+    get() = findAnnotation<Type>()?.id ?: simpleName ?: ""
+
+/**
+ * Provide an object with given name inferring target from its type using [Type] annotation
+ */
+@DFExperimental
+public inline fun <reified T : Any> Provider.provideByType(name: String): T? {
+    val target = T::class.dfType
+    return provide(target, name)
+}
+
+@DFExperimental
+public inline fun <reified T : Any> Provider.top(): Map<Name, T> {
+    val target = T::class.dfType
+    return top(target)
+}
+
+/**
+ * All objects provided by plugins with given target and type
+ */
+@DFExperimental
+public inline fun <reified T : Any> Context.gather(inherit: Boolean = true): Map<Name, T> =
+    gather<T>(T::class.dfType, inherit)
+
diff --git a/dataforge-data/api/dataforge-data.api b/dataforge-data/api/dataforge-data.api
new file mode 100644
index 00000000..06e99242
--- /dev/null
+++ b/dataforge-data/api/dataforge-data.api
@@ -0,0 +1,400 @@
+public abstract interface class hep/dataforge/data/Action {
+	public abstract fun invoke (Lhep/dataforge/data/DataNode;Lhep/dataforge/meta/Meta;)Lhep/dataforge/data/DataNode;
+	public abstract fun isTerminal ()Z
+}
+
+public final class hep/dataforge/data/Action$DefaultImpls {
+	public static fun isTerminal (Lhep/dataforge/data/Action;)Z
+}
+
+public final class hep/dataforge/data/ActionEnv {
+	public fun <init> (Lhep/dataforge/names/Name;Lhep/dataforge/meta/Meta;Lhep/dataforge/meta/Meta;)V
+	public final fun component1 ()Lhep/dataforge/names/Name;
+	public final fun component2 ()Lhep/dataforge/meta/Meta;
+	public final fun component3 ()Lhep/dataforge/meta/Meta;
+	public final fun copy (Lhep/dataforge/names/Name;Lhep/dataforge/meta/Meta;Lhep/dataforge/meta/Meta;)Lhep/dataforge/data/ActionEnv;
+	public static synthetic fun copy$default (Lhep/dataforge/data/ActionEnv;Lhep/dataforge/names/Name;Lhep/dataforge/meta/Meta;Lhep/dataforge/meta/Meta;ILjava/lang/Object;)Lhep/dataforge/data/ActionEnv;
+	public fun equals (Ljava/lang/Object;)Z
+	public final fun getActionMeta ()Lhep/dataforge/meta/Meta;
+	public final fun getMeta ()Lhep/dataforge/meta/Meta;
+	public final fun getName ()Lhep/dataforge/names/Name;
+	public fun hashCode ()I
+	public fun toString ()Ljava/lang/String;
+}
+
+public final class hep/dataforge/data/ActionKt {
+	public static final fun then (Lhep/dataforge/data/Action;Lhep/dataforge/data/Action;)Lhep/dataforge/data/Action;
+}
+
+public final class hep/dataforge/data/CoroutineMonitor : kotlin/coroutines/CoroutineContext$Element {
+	public static final field Companion Lhep/dataforge/data/CoroutineMonitor$Companion;
+	public fun <init> ()V
+	public final fun finish ()V
+	public fun fold (Ljava/lang/Object;Lkotlin/jvm/functions/Function2;)Ljava/lang/Object;
+	public fun get (Lkotlin/coroutines/CoroutineContext$Key;)Lkotlin/coroutines/CoroutineContext$Element;
+	public fun getKey ()Lkotlin/coroutines/CoroutineContext$Key;
+	public final fun getStatus ()Ljava/lang/String;
+	public final fun getTotalWork ()D
+	public final fun getWorkDone ()D
+	public fun minusKey (Lkotlin/coroutines/CoroutineContext$Key;)Lkotlin/coroutines/CoroutineContext;
+	public fun plus (Lkotlin/coroutines/CoroutineContext;)Lkotlin/coroutines/CoroutineContext;
+	public final fun setStatus (Ljava/lang/String;)V
+	public final fun setTotalWork (D)V
+	public final fun setWorkDone (D)V
+	public final fun start ()V
+}
+
+public final class hep/dataforge/data/CoroutineMonitor$Companion : kotlin/coroutines/CoroutineContext$Key {
+}
+
+public final class hep/dataforge/data/CoroutineMonitorKt {
+	public static final fun getDependencies (Lkotlinx/coroutines/Job;)Ljava/util/Collection;
+	public static final fun getMonitor (Lkotlin/coroutines/CoroutineContext;)Lhep/dataforge/data/CoroutineMonitor;
+	public static final fun getMonitor (Lkotlinx/coroutines/CoroutineScope;)Lhep/dataforge/data/CoroutineMonitor;
+	public static final fun getProgress (Lkotlinx/coroutines/Job;)D
+	public static final fun getStatus (Lkotlinx/coroutines/Job;)Ljava/lang/String;
+	public static final fun getTotalWork (Lkotlinx/coroutines/Job;)D
+	public static final fun getWorkDone (Lkotlinx/coroutines/Job;)D
+}
+
+public abstract interface class hep/dataforge/data/Data : hep/dataforge/data/Goal, hep/dataforge/meta/MetaRepr {
+	public static final field Companion Lhep/dataforge/data/Data$Companion;
+	public static final field TYPE Ljava/lang/String;
+	public abstract fun getMeta ()Lhep/dataforge/meta/Meta;
+	public abstract fun getType ()Lkotlin/reflect/KClass;
+	public abstract fun toMeta ()Lhep/dataforge/meta/Meta;
+}
+
+public final class hep/dataforge/data/Data$Companion {
+	public static final field TYPE Ljava/lang/String;
+	public final fun invoke (Ljava/lang/String;Lkotlin/reflect/KClass;Lhep/dataforge/meta/Meta;Lkotlin/coroutines/CoroutineContext;Ljava/util/Collection;Lkotlin/jvm/functions/Function2;)Lhep/dataforge/data/Data;
+	public final fun invoke (Lkotlin/reflect/KClass;Lhep/dataforge/meta/Meta;Lkotlin/coroutines/CoroutineContext;Ljava/util/Collection;Lkotlin/jvm/functions/Function2;)Lhep/dataforge/data/Data;
+	public static synthetic fun invoke$default (Lhep/dataforge/data/Data$Companion;Ljava/lang/String;Lkotlin/reflect/KClass;Lhep/dataforge/meta/Meta;Lkotlin/coroutines/CoroutineContext;Ljava/util/Collection;Lkotlin/jvm/functions/Function2;ILjava/lang/Object;)Lhep/dataforge/data/Data;
+	public static synthetic fun invoke$default (Lhep/dataforge/data/Data$Companion;Lkotlin/reflect/KClass;Lhep/dataforge/meta/Meta;Lkotlin/coroutines/CoroutineContext;Ljava/util/Collection;Lkotlin/jvm/functions/Function2;ILjava/lang/Object;)Lhep/dataforge/data/Data;
+	public final fun static (Ljava/lang/Object;Lhep/dataforge/meta/Meta;)Lhep/dataforge/data/Data;
+	public static synthetic fun static$default (Lhep/dataforge/data/Data$Companion;Ljava/lang/Object;Lhep/dataforge/meta/Meta;ILjava/lang/Object;)Lhep/dataforge/data/Data;
+}
+
+public final class hep/dataforge/data/Data$DefaultImpls {
+	public static fun toMeta (Lhep/dataforge/data/Data;)Lhep/dataforge/meta/Meta;
+}
+
+public final class hep/dataforge/data/DataCastKt {
+	public static final fun canCast (Lhep/dataforge/data/DataItem;Lkotlin/reflect/KClass;)Z
+	public static final fun cast (Lhep/dataforge/data/Data;Lkotlin/reflect/KClass;)Lhep/dataforge/data/Data;
+	public static final fun cast (Lhep/dataforge/data/DataNode;Lkotlin/reflect/KClass;)Lhep/dataforge/data/DataNode;
+	public static final fun ensureType (Lhep/dataforge/data/DataNode;Lkotlin/reflect/KClass;)V
+	public static final fun upcast (Lhep/dataforge/data/Data;Lkotlin/reflect/KClass;)Lhep/dataforge/data/Data;
+}
+
+public final class hep/dataforge/data/DataFilter : hep/dataforge/meta/Scheme {
+	public static final field Companion Lhep/dataforge/data/DataFilter$Companion;
+	public fun <init> ()V
+	public final fun getFrom ()Ljava/lang/String;
+	public final fun getPattern ()Ljava/lang/String;
+	public final fun getTo ()Ljava/lang/String;
+	public final fun setFrom (Ljava/lang/String;)V
+	public final fun setPattern (Ljava/lang/String;)V
+	public final fun setTo (Ljava/lang/String;)V
+}
+
+public final class hep/dataforge/data/DataFilter$Companion : hep/dataforge/meta/SchemeSpec {
+}
+
+public final class hep/dataforge/data/DataFilterKt {
+	public static final fun filter (Lhep/dataforge/data/DataNode;Lhep/dataforge/data/DataFilter;)Lhep/dataforge/data/DataNode;
+	public static final fun filter (Lhep/dataforge/data/DataNode;Lhep/dataforge/meta/Meta;)Lhep/dataforge/data/DataNode;
+	public static final fun filter (Lhep/dataforge/data/DataNode;Lkotlin/jvm/functions/Function1;)Lhep/dataforge/data/DataNode;
+}
+
+public abstract class hep/dataforge/data/DataItem : hep/dataforge/meta/MetaRepr {
+	public abstract fun getMeta ()Lhep/dataforge/meta/Meta;
+	public abstract fun getType ()Lkotlin/reflect/KClass;
+}
+
+public final class hep/dataforge/data/DataItem$Leaf : hep/dataforge/data/DataItem {
+	public fun <init> (Lhep/dataforge/data/Data;)V
+	public final fun getData ()Lhep/dataforge/data/Data;
+	public fun getMeta ()Lhep/dataforge/meta/Meta;
+	public fun getType ()Lkotlin/reflect/KClass;
+	public fun toMeta ()Lhep/dataforge/meta/Meta;
+}
+
+public final class hep/dataforge/data/DataItem$Node : hep/dataforge/data/DataItem {
+	public fun <init> (Lhep/dataforge/data/DataNode;)V
+	public fun getMeta ()Lhep/dataforge/meta/Meta;
+	public final fun getNode ()Lhep/dataforge/data/DataNode;
+	public fun getType ()Lkotlin/reflect/KClass;
+	public fun toMeta ()Lhep/dataforge/meta/Meta;
+}
+
+public final class hep/dataforge/data/DataJVMKt {
+	public static final fun filterIsInstance (Lhep/dataforge/data/Data;Lkotlin/reflect/KClass;)Lhep/dataforge/data/Data;
+	public static final fun filterIsInstance (Lhep/dataforge/data/DataItem;Lkotlin/reflect/KClass;)Lhep/dataforge/data/DataItem;
+	public static final fun filterIsInstance (Lhep/dataforge/data/DataNode;Lkotlin/reflect/KClass;)Lhep/dataforge/data/DataNode;
+	public static final fun get (Lhep/dataforge/data/Data;)Ljava/lang/Object;
+}
+
+public final class hep/dataforge/data/DataKt {
+	public static final fun map (Lhep/dataforge/data/Data;Lkotlin/reflect/KClass;Lkotlin/coroutines/CoroutineContext;Lhep/dataforge/meta/Meta;Lkotlin/jvm/functions/Function3;)Lhep/dataforge/data/Data;
+	public static synthetic fun map$default (Lhep/dataforge/data/Data;Lkotlin/reflect/KClass;Lkotlin/coroutines/CoroutineContext;Lhep/dataforge/meta/Meta;Lkotlin/jvm/functions/Function3;ILjava/lang/Object;)Lhep/dataforge/data/Data;
+	public static final fun reduce (Ljava/util/Map;Lkotlin/reflect/KClass;Lkotlin/coroutines/CoroutineContext;Lhep/dataforge/meta/Meta;Lkotlin/jvm/functions/Function3;)Lhep/dataforge/data/DynamicData;
+	public static synthetic fun reduce$default (Ljava/util/Map;Lkotlin/reflect/KClass;Lkotlin/coroutines/CoroutineContext;Lhep/dataforge/meta/Meta;Lkotlin/jvm/functions/Function3;ILjava/lang/Object;)Lhep/dataforge/data/DynamicData;
+}
+
+public abstract interface class hep/dataforge/data/DataNode : hep/dataforge/meta/MetaRepr {
+	public static final field Companion Lhep/dataforge/data/DataNode$Companion;
+	public static final field TYPE Ljava/lang/String;
+	public abstract fun getItems ()Ljava/util/Map;
+	public abstract fun getMeta ()Lhep/dataforge/meta/Meta;
+	public abstract fun getType ()Lkotlin/reflect/KClass;
+	public abstract fun startAll (Lkotlinx/coroutines/CoroutineScope;)Lkotlinx/coroutines/Job;
+	public abstract fun toMeta ()Lhep/dataforge/meta/Meta;
+}
+
+public final class hep/dataforge/data/DataNode$Companion {
+	public static final field TYPE Ljava/lang/String;
+	public final fun builder (Lkotlin/reflect/KClass;)Lhep/dataforge/data/DataTreeBuilder;
+	public final fun invoke (Lkotlin/reflect/KClass;Lkotlin/jvm/functions/Function1;)Lhep/dataforge/data/DataTree;
+}
+
+public final class hep/dataforge/data/DataNode$DefaultImpls {
+	public static fun startAll (Lhep/dataforge/data/DataNode;Lkotlinx/coroutines/CoroutineScope;)Lkotlinx/coroutines/Job;
+	public static fun toMeta (Lhep/dataforge/data/DataNode;)Lhep/dataforge/meta/Meta;
+}
+
+public final class hep/dataforge/data/DataNodeKt {
+	public static final fun asSequence (Lhep/dataforge/data/DataNode;)Lkotlin/sequences/Sequence;
+	public static final fun builder (Lhep/dataforge/data/DataNode;)Lhep/dataforge/data/DataTreeBuilder;
+	public static final fun dataSequence (Lhep/dataforge/data/DataNode;)Lkotlin/sequences/Sequence;
+	public static final fun datum (Lhep/dataforge/data/DataTreeBuilder;Lhep/dataforge/names/Name;Lhep/dataforge/data/Data;)V
+	public static final fun datum (Lhep/dataforge/data/DataTreeBuilder;Ljava/lang/String;Lhep/dataforge/data/Data;)V
+	public static final fun filter (Lhep/dataforge/data/DataNode;Lkotlin/jvm/functions/Function2;)Lhep/dataforge/data/DataNode;
+	public static final fun first (Lhep/dataforge/data/DataNode;)Lhep/dataforge/data/Data;
+	public static final fun get (Lhep/dataforge/data/DataNode;Lhep/dataforge/names/Name;)Lhep/dataforge/data/DataItem;
+	public static final fun get (Lhep/dataforge/data/DataNode;Ljava/lang/String;)Lhep/dataforge/data/DataItem;
+	public static final fun getData (Lhep/dataforge/data/DataItem;)Lhep/dataforge/data/Data;
+	public static final fun getNode (Lhep/dataforge/data/DataItem;)Lhep/dataforge/data/DataNode;
+	public static final fun iterator (Lhep/dataforge/data/DataNode;)Ljava/util/Iterator;
+	public static final fun join (Lhep/dataforge/data/DataNode;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
+	public static final fun node (Lhep/dataforge/data/DataTreeBuilder;Lhep/dataforge/names/Name;Lhep/dataforge/data/DataNode;)V
+	public static final fun node (Lhep/dataforge/data/DataTreeBuilder;Ljava/lang/String;Lhep/dataforge/data/DataNode;)V
+	public static final fun static (Lhep/dataforge/data/DataTreeBuilder;Lhep/dataforge/names/Name;Ljava/lang/Object;Lhep/dataforge/meta/Meta;)V
+	public static final fun static (Lhep/dataforge/data/DataTreeBuilder;Lhep/dataforge/names/Name;Ljava/lang/Object;Lkotlin/jvm/functions/Function1;)V
+	public static final fun static (Lhep/dataforge/data/DataTreeBuilder;Ljava/lang/String;Ljava/lang/Object;Lkotlin/jvm/functions/Function1;)V
+	public static synthetic fun static$default (Lhep/dataforge/data/DataTreeBuilder;Lhep/dataforge/names/Name;Ljava/lang/Object;Lhep/dataforge/meta/Meta;ILjava/lang/Object;)V
+	public static synthetic fun static$default (Lhep/dataforge/data/DataTreeBuilder;Lhep/dataforge/names/Name;Ljava/lang/Object;Lkotlin/jvm/functions/Function1;ILjava/lang/Object;)V
+	public static synthetic fun static$default (Lhep/dataforge/data/DataTreeBuilder;Ljava/lang/String;Ljava/lang/Object;Lkotlin/jvm/functions/Function1;ILjava/lang/Object;)V
+}
+
+public final class hep/dataforge/data/DataTree : hep/dataforge/data/DataNode {
+	public fun getItems ()Ljava/util/Map;
+	public fun getMeta ()Lhep/dataforge/meta/Meta;
+	public fun getType ()Lkotlin/reflect/KClass;
+	public fun startAll (Lkotlinx/coroutines/CoroutineScope;)Lkotlinx/coroutines/Job;
+	public fun toMeta ()Lhep/dataforge/meta/Meta;
+}
+
+public final class hep/dataforge/data/DataTreeBuilder {
+	public fun <init> (Lkotlin/reflect/KClass;)V
+	public final fun build ()Lhep/dataforge/data/DataTree;
+	public final fun getType ()Lkotlin/reflect/KClass;
+	public final fun meta (Lhep/dataforge/meta/Meta;)V
+	public final fun meta (Lkotlin/jvm/functions/Function1;)Lhep/dataforge/meta/MetaBuilder;
+	public final fun put (Ljava/lang/String;Lhep/dataforge/data/Data;)V
+	public final fun put (Ljava/lang/String;Lhep/dataforge/data/DataItem;)V
+	public final fun put (Ljava/lang/String;Lhep/dataforge/data/DataNode;)V
+	public final fun put (Ljava/lang/String;Lkotlin/jvm/functions/Function1;)V
+	public final fun set (Lhep/dataforge/names/Name;Lhep/dataforge/data/Data;)V
+	public final fun set (Lhep/dataforge/names/Name;Lhep/dataforge/data/DataItem;)V
+	public final fun set (Lhep/dataforge/names/Name;Lhep/dataforge/data/DataNode;)V
+	public final fun set (Lhep/dataforge/names/Name;Lhep/dataforge/data/DataTreeBuilder;)V
+	public final fun set (Lhep/dataforge/names/NameToken;Lhep/dataforge/data/Data;)V
+	public final fun set (Lhep/dataforge/names/NameToken;Lhep/dataforge/data/DataTreeBuilder;)V
+	public final fun update (Lhep/dataforge/data/DataNode;)V
+}
+
+public final class hep/dataforge/data/Dependencies : kotlin/coroutines/CoroutineContext$Element {
+	public static final field Companion Lhep/dataforge/data/Dependencies$Companion;
+	public fun <init> (Ljava/util/Collection;)V
+	public fun fold (Ljava/lang/Object;Lkotlin/jvm/functions/Function2;)Ljava/lang/Object;
+	public fun get (Lkotlin/coroutines/CoroutineContext$Key;)Lkotlin/coroutines/CoroutineContext$Element;
+	public fun getKey ()Lkotlin/coroutines/CoroutineContext$Key;
+	public final fun getValues ()Ljava/util/Collection;
+	public fun minusKey (Lkotlin/coroutines/CoroutineContext$Key;)Lkotlin/coroutines/CoroutineContext;
+	public fun plus (Lkotlin/coroutines/CoroutineContext;)Lkotlin/coroutines/CoroutineContext;
+}
+
+public final class hep/dataforge/data/Dependencies$Companion : kotlin/coroutines/CoroutineContext$Key {
+}
+
+public final class hep/dataforge/data/DynamicData : hep/dataforge/data/DynamicGoal, hep/dataforge/data/Data {
+	public fun <init> (Lkotlin/reflect/KClass;Lhep/dataforge/meta/Meta;Lkotlin/coroutines/CoroutineContext;Ljava/util/Collection;Lkotlin/jvm/functions/Function2;)V
+	public synthetic fun <init> (Lkotlin/reflect/KClass;Lhep/dataforge/meta/Meta;Lkotlin/coroutines/CoroutineContext;Ljava/util/Collection;Lkotlin/jvm/functions/Function2;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
+	public fun getMeta ()Lhep/dataforge/meta/Meta;
+	public fun getType ()Lkotlin/reflect/KClass;
+	public fun toMeta ()Lhep/dataforge/meta/Meta;
+}
+
+public class hep/dataforge/data/DynamicGoal : hep/dataforge/data/Goal {
+	public fun <init> (Lkotlin/coroutines/CoroutineContext;Ljava/util/Collection;Lkotlin/jvm/functions/Function2;)V
+	public synthetic fun <init> (Lkotlin/coroutines/CoroutineContext;Ljava/util/Collection;Lkotlin/jvm/functions/Function2;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
+	public final fun getBlock ()Lkotlin/jvm/functions/Function2;
+	public fun getDependencies ()Ljava/util/Collection;
+	public final fun getResult ()Lkotlinx/coroutines/Deferred;
+	public fun reset ()V
+	public fun startAsync (Lkotlinx/coroutines/CoroutineScope;)Lkotlinx/coroutines/Deferred;
+}
+
+public final class hep/dataforge/data/FragmentRule {
+	public field result Lkotlin/jvm/functions/Function2;
+	public fun <init> (Lhep/dataforge/names/Name;Lhep/dataforge/meta/MetaBuilder;)V
+	public final fun getMeta ()Lhep/dataforge/meta/MetaBuilder;
+	public final fun getName ()Lhep/dataforge/names/Name;
+	public final fun getResult ()Lkotlin/jvm/functions/Function2;
+	public final fun result (Lkotlin/jvm/functions/Function2;)V
+	public final fun setMeta (Lhep/dataforge/meta/MetaBuilder;)V
+	public final fun setResult (Lkotlin/jvm/functions/Function2;)V
+}
+
+public abstract interface class hep/dataforge/data/Goal {
+	public static final field Companion Lhep/dataforge/data/Goal$Companion;
+	public abstract fun getDependencies ()Ljava/util/Collection;
+	public abstract fun getResult ()Lkotlinx/coroutines/Deferred;
+	public abstract fun reset ()V
+	public abstract fun startAsync (Lkotlinx/coroutines/CoroutineScope;)Lkotlinx/coroutines/Deferred;
+}
+
+public final class hep/dataforge/data/Goal$Companion {
+}
+
+public final class hep/dataforge/data/GoalKt {
+	public static final fun await (Lhep/dataforge/data/Goal;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
+	public static final fun isComplete (Lhep/dataforge/data/Goal;)Z
+	public static final fun map (Lhep/dataforge/data/Goal;Lkotlin/coroutines/CoroutineContext;Lkotlin/jvm/functions/Function3;)Lhep/dataforge/data/Goal;
+	public static synthetic fun map$default (Lhep/dataforge/data/Goal;Lkotlin/coroutines/CoroutineContext;Lkotlin/jvm/functions/Function3;ILjava/lang/Object;)Lhep/dataforge/data/Goal;
+	public static final fun reduce (Ljava/util/Collection;Lkotlin/coroutines/CoroutineContext;Lkotlin/jvm/functions/Function3;)Lhep/dataforge/data/Goal;
+	public static final fun reduce (Ljava/util/Map;Lkotlin/coroutines/CoroutineContext;Lkotlin/jvm/functions/Function3;)Lhep/dataforge/data/Goal;
+	public static synthetic fun reduce$default (Ljava/util/Collection;Lkotlin/coroutines/CoroutineContext;Lkotlin/jvm/functions/Function3;ILjava/lang/Object;)Lhep/dataforge/data/Goal;
+	public static synthetic fun reduce$default (Ljava/util/Map;Lkotlin/coroutines/CoroutineContext;Lkotlin/jvm/functions/Function3;ILjava/lang/Object;)Lhep/dataforge/data/Goal;
+}
+
+public abstract interface class hep/dataforge/data/GroupRule {
+	public static final field Companion Lhep/dataforge/data/GroupRule$Companion;
+	public abstract fun invoke (Lhep/dataforge/data/DataNode;)Ljava/util/Map;
+}
+
+public final class hep/dataforge/data/GroupRule$Companion {
+	public final fun byMeta (Lhep/dataforge/meta/Meta;)Lhep/dataforge/data/GroupRule;
+	public final fun byValue (Ljava/lang/String;Ljava/lang/String;)Lhep/dataforge/data/GroupRule;
+}
+
+public final class hep/dataforge/data/JoinGroup {
+	public field result Lkotlin/jvm/functions/Function3;
+	public fun <init> (Ljava/lang/String;Lhep/dataforge/data/DataNode;)V
+	public final fun getMeta ()Lhep/dataforge/meta/MetaBuilder;
+	public final fun getName ()Ljava/lang/String;
+	public final fun getResult ()Lkotlin/jvm/functions/Function3;
+	public final fun result (Lkotlin/jvm/functions/Function3;)V
+	public final fun setMeta (Lhep/dataforge/meta/MetaBuilder;)V
+	public final fun setName (Ljava/lang/String;)V
+	public final fun setResult (Lkotlin/jvm/functions/Function3;)V
+}
+
+public final class hep/dataforge/data/MapAction : hep/dataforge/data/Action {
+	public fun <init> (Lkotlin/reflect/KClass;Lkotlin/reflect/KClass;Lkotlin/jvm/functions/Function1;)V
+	public final fun getInputType ()Lkotlin/reflect/KClass;
+	public final fun getOutputType ()Lkotlin/reflect/KClass;
+	public fun invoke (Lhep/dataforge/data/DataNode;Lhep/dataforge/meta/Meta;)Lhep/dataforge/data/DataNode;
+	public fun isTerminal ()Z
+}
+
+public final class hep/dataforge/data/MapActionBuilder {
+	public field result Lkotlin/jvm/functions/Function3;
+	public fun <init> (Lhep/dataforge/names/Name;Lhep/dataforge/meta/MetaBuilder;Lhep/dataforge/meta/Meta;)V
+	public final fun getActionMeta ()Lhep/dataforge/meta/Meta;
+	public final fun getMeta ()Lhep/dataforge/meta/MetaBuilder;
+	public final fun getName ()Lhep/dataforge/names/Name;
+	public final fun getResult ()Lkotlin/jvm/functions/Function3;
+	public final fun result (Lkotlin/jvm/functions/Function3;)V
+	public final fun setMeta (Lhep/dataforge/meta/MetaBuilder;)V
+	public final fun setName (Lhep/dataforge/names/Name;)V
+	public final fun setResult (Lkotlin/jvm/functions/Function3;)V
+}
+
+public final class hep/dataforge/data/NamedData : hep/dataforge/data/Data {
+	public fun <init> (Ljava/lang/String;Lhep/dataforge/data/Data;)V
+	public fun getDependencies ()Ljava/util/Collection;
+	public fun getMeta ()Lhep/dataforge/meta/Meta;
+	public final fun getName ()Ljava/lang/String;
+	public fun getResult ()Lkotlinx/coroutines/Deferred;
+	public fun getType ()Lkotlin/reflect/KClass;
+	public fun reset ()V
+	public fun startAsync (Lkotlinx/coroutines/CoroutineScope;)Lkotlinx/coroutines/Deferred;
+	public fun toMeta ()Lhep/dataforge/meta/Meta;
+}
+
+public final class hep/dataforge/data/ReduceAction : hep/dataforge/data/Action {
+	public fun <init> (Lkotlin/reflect/KClass;Lkotlin/reflect/KClass;Lkotlin/jvm/functions/Function1;)V
+	public final fun getInputType ()Lkotlin/reflect/KClass;
+	public final fun getOutputType ()Lkotlin/reflect/KClass;
+	public fun invoke (Lhep/dataforge/data/DataNode;Lhep/dataforge/meta/Meta;)Lhep/dataforge/data/DataNode;
+	public fun isTerminal ()Z
+}
+
+public final class hep/dataforge/data/ReduceActionKt {
+	public static final fun get (Ljava/util/Map;Ljava/lang/String;)Ljava/lang/Object;
+}
+
+public final class hep/dataforge/data/ReduceGroupBuilder {
+	public fun <init> (Lhep/dataforge/meta/Meta;)V
+	public final fun byValue (Ljava/lang/String;Ljava/lang/String;Lkotlin/jvm/functions/Function1;)V
+	public static synthetic fun byValue$default (Lhep/dataforge/data/ReduceGroupBuilder;Ljava/lang/String;Ljava/lang/String;Lkotlin/jvm/functions/Function1;ILjava/lang/Object;)V
+	public final fun getActionMeta ()Lhep/dataforge/meta/Meta;
+	public final fun group (Ljava/lang/String;Lhep/dataforge/data/DataFilter;Lkotlin/jvm/functions/Function1;)V
+	public final fun group (Ljava/lang/String;Lkotlin/jvm/functions/Function2;Lkotlin/jvm/functions/Function1;)V
+	public final fun result (Ljava/lang/String;Lkotlin/jvm/functions/Function3;)V
+}
+
+public final class hep/dataforge/data/SplitAction : hep/dataforge/data/Action {
+	public fun <init> (Lkotlin/reflect/KClass;Lkotlin/reflect/KClass;Lkotlin/jvm/functions/Function1;)V
+	public final fun getInputType ()Lkotlin/reflect/KClass;
+	public final fun getOutputType ()Lkotlin/reflect/KClass;
+	public fun invoke (Lhep/dataforge/data/DataNode;Lhep/dataforge/meta/Meta;)Lhep/dataforge/data/DataNode;
+	public fun isTerminal ()Z
+}
+
+public final class hep/dataforge/data/SplitBuilder {
+	public fun <init> (Lhep/dataforge/names/Name;Lhep/dataforge/meta/Meta;)V
+	public final fun fragment (Ljava/lang/String;Lkotlin/jvm/functions/Function1;)V
+	public final fun getMeta ()Lhep/dataforge/meta/Meta;
+	public final fun getName ()Lhep/dataforge/names/Name;
+}
+
+public final class hep/dataforge/data/StaticData : hep/dataforge/data/StaticGoal, hep/dataforge/data/Data {
+	public fun <init> (Ljava/lang/Object;Lhep/dataforge/meta/Meta;)V
+	public synthetic fun <init> (Ljava/lang/Object;Lhep/dataforge/meta/Meta;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
+	public fun getMeta ()Lhep/dataforge/meta/Meta;
+	public fun getType ()Lkotlin/reflect/KClass;
+	public fun toMeta ()Lhep/dataforge/meta/Meta;
+}
+
+public class hep/dataforge/data/StaticGoal : hep/dataforge/data/Goal {
+	public fun <init> (Ljava/lang/Object;)V
+	public fun getDependencies ()Ljava/util/Collection;
+	public fun getResult ()Lkotlinx/coroutines/Deferred;
+	public final fun getValue ()Ljava/lang/Object;
+	public fun reset ()V
+	public fun startAsync (Lkotlinx/coroutines/CoroutineScope;)Lkotlinx/coroutines/Deferred;
+}
+
+public final class hep/dataforge/data/TypeFilteredDataNode : hep/dataforge/data/DataNode {
+	public fun <init> (Lhep/dataforge/data/DataNode;Lkotlin/reflect/KClass;)V
+	public fun getItems ()Ljava/util/Map;
+	public fun getMeta ()Lhep/dataforge/meta/Meta;
+	public final fun getOrigin ()Lhep/dataforge/data/DataNode;
+	public fun getType ()Lkotlin/reflect/KClass;
+	public fun startAll (Lkotlinx/coroutines/CoroutineScope;)Lkotlinx/coroutines/Job;
+	public fun toMeta ()Lhep/dataforge/meta/Meta;
+}
+
diff --git a/dataforge-data/build.gradle.kts b/dataforge-data/build.gradle.kts
index 793f551b..436d9428 100644
--- a/dataforge-data/build.gradle.kts
+++ b/dataforge-data/build.gradle.kts
@@ -1,29 +1,23 @@
 plugins {
-    id("scientifik.mpp")
+    id("ru.mipt.npm.mpp")
+    id("ru.mipt.npm.native")
 }
 
-val coroutinesVersion: String = Scientifik.coroutinesVersion
+kscience{
+    useCoroutines()
+}
 
 kotlin {
     sourceSets {
-        val commonMain by getting{
+        commonMain{
             dependencies {
                 api(project(":dataforge-meta"))
-                api("org.jetbrains.kotlinx:kotlinx-coroutines-core-common:$coroutinesVersion")
             }
         }
-
-        val jvmMain by getting{
-            dependencies {
-                api("org.jetbrains.kotlinx:kotlinx-coroutines-core:$coroutinesVersion")
+        jvmMain{
+            dependencies{
                 api(kotlin("reflect"))
             }
         }
-
-        val jsMain by getting{
-            dependencies {
-                api("org.jetbrains.kotlinx:kotlinx-coroutines-core-js:$coroutinesVersion")
-            }
-        }
     }
 }
\ No newline at end of file
diff --git a/dataforge-data/src/commonMain/kotlin/hep/dataforge/data/Action.kt b/dataforge-data/src/commonMain/kotlin/hep/dataforge/data/Action.kt
index cf030c75..d747587e 100644
--- a/dataforge-data/src/commonMain/kotlin/hep/dataforge/data/Action.kt
+++ b/dataforge-data/src/commonMain/kotlin/hep/dataforge/data/Action.kt
@@ -5,23 +5,23 @@ import hep.dataforge.meta.Meta
 /**
  * A simple data transformation on a data node
  */
-interface Action<in T : Any, out R : Any> {
+public interface Action<in T : Any, out R : Any> {
     /**
      * Transform the data in the node, producing a new node. By default it is assumed that all calculations are lazy
      * so not actual computation is started at this moment
      */
-    operator fun invoke(node: DataNode<T>, meta: Meta): DataNode<R>
+    public operator fun invoke(node: DataNode<T>, meta: Meta): DataNode<R>
 
     /**
      * Terminal action is the one that could not be invoked lazily and requires some kind of blocking computation to invoke
      */
-    val isTerminal: Boolean get() = false
+    public val isTerminal: Boolean get() = false
 }
 
 /**
  * Action composition. The result is terminal if one of its parts is terminal
  */
-infix fun <T : Any, I : Any, R : Any> Action<T, I>.then(action: Action<I, R>): Action<T, R> {
+public infix fun <T : Any, I : Any, R : Any> Action<T, I>.then(action: Action<I, R>): Action<T, R> {
     // TODO introduce composite action and add optimize by adding action to the list
     return object : Action<T, R> {
         override fun invoke(node: DataNode<T>, meta: Meta): DataNode<R> {
diff --git a/dataforge-data/src/commonMain/kotlin/hep/dataforge/data/CoroutineMonitor.kt b/dataforge-data/src/commonMain/kotlin/hep/dataforge/data/CoroutineMonitor.kt
index 8cbd6192..d1c0d55e 100644
--- a/dataforge-data/src/commonMain/kotlin/hep/dataforge/data/CoroutineMonitor.kt
+++ b/dataforge-data/src/commonMain/kotlin/hep/dataforge/data/CoroutineMonitor.kt
@@ -1,48 +1,58 @@
 package hep.dataforge.data
 
+import hep.dataforge.meta.DFExperimental
 import kotlinx.coroutines.CoroutineScope
 import kotlinx.coroutines.Job
 import kotlin.coroutines.CoroutineContext
 
+
+
 /**
  * A monitor of goal state that could be accessed only form inside the goal
  */
-class CoroutineMonitor : CoroutineContext.Element {
+@DFExperimental
+public class CoroutineMonitor : CoroutineContext.Element {
     override val key: CoroutineContext.Key<*> get() = CoroutineMonitor
 
-    var totalWork: Double = 1.0
-    var workDone: Double = 0.0
-    var status: String = ""
+    public var totalWork: Double = 1.0
+    public var workDone: Double = 0.0
+    public var status: String = ""
 
     /**
      * Mark the goal as started
      */
-    fun start() {
+    public fun start() {
 
     }
 
     /**
      * Mark the goal as completed
      */
-    fun finish() {
+    public fun finish() {
         workDone = totalWork
     }
 
-    companion object : CoroutineContext.Key<CoroutineMonitor>
+    public companion object : CoroutineContext.Key<CoroutineMonitor>
 }
 
-class Dependencies(val values: Collection<Job>) : CoroutineContext.Element {
+public class Dependencies(public val values: Collection<Job>) : CoroutineContext.Element {
     override val key: CoroutineContext.Key<*> get() = Dependencies
 
-    companion object : CoroutineContext.Key<Dependencies>
+    public companion object : CoroutineContext.Key<Dependencies>
 }
 
-val CoroutineContext.monitor: CoroutineMonitor? get() = this[CoroutineMonitor]
-val CoroutineScope.monitor: CoroutineMonitor? get() = coroutineContext.monitor
+@DFExperimental
+public val CoroutineContext.monitor: CoroutineMonitor? get() = this[CoroutineMonitor]
+@DFExperimental
+public val CoroutineScope.monitor: CoroutineMonitor? get() = coroutineContext.monitor
 
-val Job.dependencies: Collection<Job> get() = this[Dependencies]?.values ?: emptyList()
+public val Job.dependencies: Collection<Job> get() = this[Dependencies]?.values ?: emptyList()
 
-val Job.totalWork: Double get() = dependencies.sumByDouble { totalWork } + (monitor?.totalWork ?: 0.0)
-val Job.workDone: Double get() = dependencies.sumByDouble { workDone } + (monitor?.workDone ?: 0.0)
-val Job.status: String get() = monitor?.status ?: ""
-val Job.progress: Double get() = workDone / totalWork
\ No newline at end of file
+@DFExperimental
+public val Job.totalWork: Double get() = dependencies.sumByDouble { totalWork } + (monitor?.totalWork ?: 0.0)
+@DFExperimental
+public val Job.workDone: Double get() = dependencies.sumByDouble { workDone } + (monitor?.workDone ?: 0.0)
+@DFExperimental
+public val Job.status: String get() = monitor?.status ?: ""
+@DFExperimental
+public val Job.progress: Double get() = workDone / totalWork
\ No newline at end of file
diff --git a/dataforge-data/src/commonMain/kotlin/hep/dataforge/data/Data.kt b/dataforge-data/src/commonMain/kotlin/hep/dataforge/data/Data.kt
index 233ea164..c573aad8 100644
--- a/dataforge-data/src/commonMain/kotlin/hep/dataforge/data/Data.kt
+++ b/dataforge-data/src/commonMain/kotlin/hep/dataforge/data/Data.kt
@@ -11,15 +11,16 @@ import kotlin.reflect.KClass
 /**
  * A data element characterized by its meta
  */
-interface Data<out T : Any> : Goal<T>, MetaRepr{
+public interface Data<out T : Any> : Goal<T>, MetaRepr{
     /**
      * Type marker for the data. The type is known before the calculation takes place so it could be checked.
      */
-    val type: KClass<out T>
+    public val type: KClass<out T>
+
     /**
      * Meta for the data
      */
-    val meta: Meta
+    public val meta: Meta
 
     override fun toMeta(): Meta  = Meta {
         "type" put (type.simpleName?:"undefined")
@@ -28,10 +29,10 @@ interface Data<out T : Any> : Goal<T>, MetaRepr{
         }
     }
 
-    companion object {
-        const val TYPE = "data"
+    public companion object {
+        public const val TYPE: String = "data"
 
-        operator fun <T : Any> invoke(
+        public operator fun <T : Any> invoke(
             type: KClass<out T>,
             meta: Meta = Meta.EMPTY,
             context: CoroutineContext = EmptyCoroutineContext,
@@ -39,14 +40,14 @@ interface Data<out T : Any> : Goal<T>, MetaRepr{
             block: suspend CoroutineScope.() -> T
         ): Data<T> = DynamicData(type, meta, context, dependencies, block)
 
-        inline operator fun <reified T : Any> invoke(
+        public inline operator fun <reified T : Any> invoke(
             meta: Meta = Meta.EMPTY,
             context: CoroutineContext = EmptyCoroutineContext,
             dependencies: Collection<Data<*>> = emptyList(),
             noinline block: suspend CoroutineScope.() -> T
         ): Data<T> = invoke(T::class, meta, context, dependencies, block)
 
-        operator fun <T : Any> invoke(
+        public operator fun <T : Any> invoke(
             name: String,
             type: KClass<out T>,
             meta: Meta = Meta.EMPTY,
@@ -55,7 +56,7 @@ interface Data<out T : Any> : Goal<T>, MetaRepr{
             block: suspend CoroutineScope.() -> T
         ): Data<T> = NamedData(name, invoke(type, meta, context, dependencies, block))
 
-        inline operator fun <reified T : Any> invoke(
+        public inline operator fun <reified T : Any> invoke(
             name: String,
             meta: Meta = Meta.EMPTY,
             context: CoroutineContext = EmptyCoroutineContext,
@@ -64,13 +65,13 @@ interface Data<out T : Any> : Goal<T>, MetaRepr{
         ): Data<T> =
             invoke(name, T::class, meta, context, dependencies, block)
 
-        fun <T : Any> static(value: T, meta: Meta = Meta.EMPTY): Data<T> =
+        public fun <T : Any> static(value: T, meta: Meta = Meta.EMPTY): Data<T> =
             StaticData(value, meta)
     }
 }
 
 
-class DynamicData<T : Any>(
+public class DynamicData<T : Any>(
     override val type: KClass<out T>,
     override val meta: Meta = Meta.EMPTY,
     context: CoroutineContext = EmptyCoroutineContext,
@@ -78,16 +79,16 @@ class DynamicData<T : Any>(
     block: suspend CoroutineScope.() -> T
 ) : Data<T>, DynamicGoal<T>(context, dependencies, block)
 
-class StaticData<T : Any>(
+public class StaticData<T : Any>(
     value: T,
     override val meta: Meta = Meta.EMPTY
 ) : Data<T>, StaticGoal<T>(value) {
     override val type: KClass<out T> get() = value::class
 }
 
-class NamedData<out T : Any>(val name: String, data: Data<T>) : Data<T> by data
+public class NamedData<out T : Any>(public val name: String, data: Data<T>) : Data<T> by data
 
-fun <T : Any, R : Any> Data<T>.map(
+public fun <T : Any, R : Any> Data<T>.map(
     outputType: KClass<out R>,
     coroutineContext: CoroutineContext = EmptyCoroutineContext,
     meta: Meta = this.meta,
@@ -100,7 +101,7 @@ fun <T : Any, R : Any> Data<T>.map(
 /**
  * Create a data pipe
  */
-inline fun <T : Any, reified R : Any> Data<T>.map(
+public inline fun <T : Any, reified R : Any> Data<T>.map(
     coroutineContext: CoroutineContext = EmptyCoroutineContext,
     meta: Meta = this.meta,
     noinline block: suspend CoroutineScope.(T) -> R
@@ -111,7 +112,7 @@ inline fun <T : Any, reified R : Any> Data<T>.map(
 /**
  * Create a joined data.
  */
-inline fun <T : Any, reified R : Any> Collection<Data<T>>.reduce(
+public inline fun <T : Any, reified R : Any> Collection<Data<T>>.reduce(
     coroutineContext: CoroutineContext = EmptyCoroutineContext,
     meta: Meta,
     noinline block: suspend CoroutineScope.(Collection<T>) -> R
@@ -124,7 +125,7 @@ inline fun <T : Any, reified R : Any> Collection<Data<T>>.reduce(
     block(map { run { it.await() } })
 }
 
-fun <K, T : Any, R : Any> Map<K, Data<T>>.reduce(
+public fun <K, T : Any, R : Any> Map<K, Data<T>>.reduce(
     outputType: KClass<out R>,
     coroutineContext: CoroutineContext = EmptyCoroutineContext,
     meta: Meta,
@@ -145,7 +146,7 @@ fun <K, T : Any, R : Any> Map<K, Data<T>>.reduce(
  * @param T type of the input goal
  * @param R type of the result goal
  */
-inline fun <K, T : Any, reified R : Any> Map<K, Data<T>>.reduce(
+public inline fun <K, T : Any, reified R : Any> Map<K, Data<T>>.reduce(
     coroutineContext: CoroutineContext = EmptyCoroutineContext,
     meta: Meta,
     noinline block: suspend CoroutineScope.(Map<K, T>) -> R
diff --git a/dataforge-data/src/commonMain/kotlin/hep/dataforge/data/DataFilter.kt b/dataforge-data/src/commonMain/kotlin/hep/dataforge/data/DataFilter.kt
index b24f87a2..df19acd0 100644
--- a/dataforge-data/src/commonMain/kotlin/hep/dataforge/data/DataFilter.kt
+++ b/dataforge-data/src/commonMain/kotlin/hep/dataforge/data/DataFilter.kt
@@ -4,31 +4,29 @@ import hep.dataforge.meta.*
 import hep.dataforge.names.toName
 
 
-class DataFilter : Scheme() {
+public class DataFilter : Scheme() {
     /**
      * A source node for the filter
      */
-    var from by string()
+    public var from: String? by string()
     /**
      * A target placement for the filtered node
      */
-    var to by string()
+    public var to: String? by string()
     /**
      * A regular expression pattern for the filter
      */
-    var pattern by string(".*")
+    public var pattern: String by string(".*")
 //    val prefix by string()
 //    val suffix by string()
 
-    fun isEmpty(): Boolean = config.isEmpty()
-
-    companion object : SchemeSpec<DataFilter>(::DataFilter)
+    public companion object : SchemeSpec<DataFilter>(::DataFilter)
 }
 
 /**
  * Apply meta-based filter to given data node
  */
-fun <T : Any> DataNode<T>.filter(filter: DataFilter): DataNode<T> {
+public fun <T : Any> DataNode<T>.filter(filter: DataFilter): DataNode<T> {
     val sourceNode = filter.from?.let { get(it.toName()).node } ?: this@filter
     val regex = filter.pattern.toRegex()
     val targetNode = DataTreeBuilder(type).apply {
@@ -46,10 +44,10 @@ fun <T : Any> DataNode<T>.filter(filter: DataFilter): DataNode<T> {
 /**
  * Filter data using [DataFilter] specification
  */
-fun <T : Any> DataNode<T>.filter(filter: Meta): DataNode<T> = filter(DataFilter.wrap(filter))
+public fun <T : Any> DataNode<T>.filter(filter: Meta): DataNode<T> = filter(DataFilter.read(filter))
 
 /**
  * Filter data using [DataFilter] builder
  */
-fun <T : Any> DataNode<T>.filter(filterBuilder: DataFilter.() -> Unit): DataNode<T> =
+public fun <T : Any> DataNode<T>.filter(filterBuilder: DataFilter.() -> Unit): DataNode<T> =
     filter(DataFilter(filterBuilder))
\ No newline at end of file
diff --git a/dataforge-data/src/commonMain/kotlin/hep/dataforge/data/DataNode.kt b/dataforge-data/src/commonMain/kotlin/hep/dataforge/data/DataNode.kt
index 246d9796..23fea9ef 100644
--- a/dataforge-data/src/commonMain/kotlin/hep/dataforge/data/DataNode.kt
+++ b/dataforge-data/src/commonMain/kotlin/hep/dataforge/data/DataNode.kt
@@ -11,12 +11,12 @@ import kotlin.collections.component2
 import kotlin.collections.set
 import kotlin.reflect.KClass
 
-sealed class DataItem<out T : Any> : MetaRepr {
-    abstract val type: KClass<out T>
+public sealed class DataItem<out T : Any> : MetaRepr {
+    public abstract val type: KClass<out T>
 
-    abstract val meta: Meta
+    public abstract val meta: Meta
 
-    class Node<out T : Any>(val node: DataNode<T>) : DataItem<T>() {
+    public class Node<out T : Any>(public val node: DataNode<T>) : DataItem<T>() {
         override val type: KClass<out T> get() = node.type
 
         override fun toMeta(): Meta = node.toMeta()
@@ -24,7 +24,7 @@ sealed class DataItem<out T : Any> : MetaRepr {
         override val meta: Meta get() = node.meta
     }
 
-    class Leaf<out T : Any>(val data: Data<T>) : DataItem<T>() {
+    public class Leaf<out T : Any>(public val data: Data<T>) : DataItem<T>() {
         override val type: KClass<out T> get() = data.type
 
         override fun toMeta(): Meta = data.toMeta()
@@ -36,16 +36,16 @@ sealed class DataItem<out T : Any> : MetaRepr {
 /**
  * A tree-like data structure grouped into the node. All data inside the node must inherit its type
  */
-interface DataNode<out T : Any> : MetaRepr {
+public interface DataNode<out T : Any> : MetaRepr {
 
     /**
      * The minimal common ancestor to all data in the node
      */
-    val type: KClass<out T>
+    public val type: KClass<out T>
 
-    val items: Map<NameToken, DataItem<T>>
+    public val items: Map<NameToken, DataItem<T>>
 
-    val meta: Meta
+    public val meta: Meta
 
     override fun toMeta(): Meta = Meta {
         "type" put (type.simpleName ?: "undefined")
@@ -60,7 +60,7 @@ interface DataNode<out T : Any> : MetaRepr {
      * Start computation for all goals in data node and return a job for the whole node
      */
     @Suppress("DeferredResultUnused")
-    fun CoroutineScope.startAll(): Job = launch {
+    public fun CoroutineScope.startAll(): Job = launch {
         items.values.forEach {
             when (it) {
                 is DataItem.Node<*> -> it.node.run { startAll() }
@@ -69,36 +69,36 @@ interface DataNode<out T : Any> : MetaRepr {
         }
     }
 
-    companion object {
-        const val TYPE = "dataNode"
+    public companion object {
+        public const val TYPE: String = "dataNode"
 
-        operator fun <T : Any> invoke(type: KClass<out T>, block: DataTreeBuilder<T>.() -> Unit) =
+        public operator fun <T : Any> invoke(type: KClass<out T>, block: DataTreeBuilder<T>.() -> Unit): DataTree<T> =
             DataTreeBuilder(type).apply(block).build()
 
-        inline operator fun <reified T : Any> invoke(noinline block: DataTreeBuilder<T>.() -> Unit) =
+        public inline operator fun <reified T : Any> invoke(noinline block: DataTreeBuilder<T>.() -> Unit): DataTree<T> =
             DataTreeBuilder(T::class).apply(block).build()
 
-        fun <T : Any> builder(type: KClass<out T>) = DataTreeBuilder(type)
+        public fun <T : Any> builder(type: KClass<out T>): DataTreeBuilder<T> = DataTreeBuilder(type)
     }
 }
 
-suspend fun <T: Any> DataNode<T>.join(): Unit = coroutineScope { startAll().join() }
+public suspend fun <T: Any> DataNode<T>.join(): Unit = coroutineScope { startAll().join() }
 
-val <T : Any> DataItem<T>?.node: DataNode<T>? get() = (this as? DataItem.Node<T>)?.node
-val <T : Any> DataItem<T>?.data: Data<T>? get() = (this as? DataItem.Leaf<T>)?.data
+public val <T : Any> DataItem<T>?.node: DataNode<T>? get() = (this as? DataItem.Node<T>)?.node
+public val <T : Any> DataItem<T>?.data: Data<T>? get() = (this as? DataItem.Leaf<T>)?.data
 
-operator fun <T : Any> DataNode<T>.get(name: Name): DataItem<T>? = when (name.length) {
+public operator fun <T : Any> DataNode<T>.get(name: Name): DataItem<T>? = when (name.length) {
     0 -> error("Empty name")
-    1 -> items[name.first()]
-    else -> get(name.first()!!.asName()).node?.get(name.cutFirst())
+    1 -> items[name.firstOrNull()]
+    else -> get(name.firstOrNull()!!.asName()).node?.get(name.cutFirst())
 }
 
-operator fun <T : Any> DataNode<T>.get(name: String): DataItem<T>? = get(name.toName())
+public operator fun <T : Any> DataNode<T>.get(name: String): DataItem<T>? = get(name.toName())
 
 /**
  * Sequence of all children including nodes
  */
-fun <T : Any> DataNode<T>.asSequence(): Sequence<Pair<Name, DataItem<T>>> = sequence {
+public fun <T : Any> DataNode<T>.asSequence(): Sequence<Pair<Name, DataItem<T>>> = sequence {
     items.forEach { (head, item) ->
         yield(head.asName() to item)
         if (item is DataItem.Node) {
@@ -112,7 +112,7 @@ fun <T : Any> DataNode<T>.asSequence(): Sequence<Pair<Name, DataItem<T>>> = sequ
 /**
  * Sequence of data entries
  */
-fun <T : Any> DataNode<T>.dataSequence(): Sequence<Pair<Name, Data<T>>> = sequence {
+public fun <T : Any> DataNode<T>.dataSequence(): Sequence<Pair<Name, Data<T>>> = sequence {
     items.forEach { (head, item) ->
         when (item) {
             is DataItem.Leaf -> yield(head.asName() to item.data)
@@ -125,9 +125,9 @@ fun <T : Any> DataNode<T>.dataSequence(): Sequence<Pair<Name, Data<T>>> = sequen
     }
 }
 
-operator fun <T : Any> DataNode<T>.iterator(): Iterator<Pair<Name, DataItem<T>>> = asSequence().iterator()
+public operator fun <T : Any> DataNode<T>.iterator(): Iterator<Pair<Name, DataItem<T>>> = asSequence().iterator()
 
-class DataTree<out T : Any> internal constructor(
+public class DataTree<out T : Any> internal constructor(
     override val type: KClass<out T>,
     override val items: Map<NameToken, DataItem<T>>,
     override val meta: Meta
@@ -142,17 +142,17 @@ private sealed class DataTreeBuilderItem<out T : Any> {
  * A builder for a DataTree.
  */
 @DFBuilder
-class DataTreeBuilder<T : Any>(val type: KClass<out T>) {
+public class DataTreeBuilder<T : Any>(public val type: KClass<out T>) {
     private val map = HashMap<NameToken, DataTreeBuilderItem<T>>()
 
     private var meta = MetaBuilder()
 
-    operator fun set(token: NameToken, node: DataTreeBuilder<out T>) {
+    public operator fun set(token: NameToken, node: DataTreeBuilder<out T>) {
         if (map.containsKey(token)) error("Tree entry with name $token is not empty")
         map[token] = DataTreeBuilderItem.Node(node)
     }
 
-    operator fun set(token: NameToken, data: Data<T>) {
+    public operator fun set(token: NameToken, data: Data<T>) {
         if (map.containsKey(token)) error("Tree entry with name $token is not empty")
         map[token] = DataTreeBuilderItem.Leaf(data)
     }
@@ -168,30 +168,30 @@ class DataTreeBuilder<T : Any>(val type: KClass<out T>) {
     private fun buildNode(name: Name): DataTreeBuilder<T> {
         return when (name.length) {
             0 -> this
-            1 -> buildNode(name.first()!!)
-            else -> buildNode(name.first()!!).buildNode(name.cutFirst())
+            1 -> buildNode(name.firstOrNull()!!)
+            else -> buildNode(name.firstOrNull()!!).buildNode(name.cutFirst())
         }
     }
 
-    operator fun set(name: Name, data: Data<T>) {
+    public operator fun set(name: Name, data: Data<T>) {
         when (name.length) {
             0 -> error("Can't add data with empty name")
-            1 -> set(name.first()!!, data)
-            2 -> buildNode(name.cutLast())[name.last()!!] = data
+            1 -> set(name.firstOrNull()!!, data)
+            2 -> buildNode(name.cutLast())[name.lastOrNull()!!] = data
         }
     }
 
-    operator fun set(name: Name, node: DataTreeBuilder<out T>) {
+    public operator fun set(name: Name, node: DataTreeBuilder<out T>) {
         when (name.length) {
             0 -> error("Can't add data with empty name")
-            1 -> set(name.first()!!, node)
-            2 -> buildNode(name.cutLast())[name.last()!!] = node
+            1 -> set(name.firstOrNull()!!, node)
+            2 -> buildNode(name.cutLast())[name.lastOrNull()!!] = node
         }
     }
 
-    operator fun set(name: Name, node: DataNode<T>) = set(name, node.builder())
+    public operator fun set(name: Name, node: DataNode<T>): Unit = set(name, node.builder())
 
-    operator fun set(name: Name, item: DataItem<T>) = when (item) {
+    public operator fun set(name: Name, item: DataItem<T>): Unit = when (item) {
         is DataItem.Node<T> -> set(name, item.node.builder())
         is DataItem.Leaf<T> -> set(name, item.data)
     }
@@ -199,25 +199,25 @@ class DataTreeBuilder<T : Any>(val type: KClass<out T>) {
     /**
      * Append data to node
      */
-    infix fun String.put(data: Data<T>) = set(toName(), data)
+    public infix fun String.put(data: Data<T>): Unit = set(toName(), data)
 
     /**
      * Append node
      */
-    infix fun String.put(node: DataNode<T>) = set(toName(), node)
+    public infix fun String.put(node: DataNode<T>): Unit = set(toName(), node)
 
-    infix fun String.put(item: DataItem<T>) = set(toName(), item)
+    public infix fun String.put(item: DataItem<T>): Unit = set(toName(), item)
 
     /**
      * Build and append node
      */
-    infix fun String.put(block: DataTreeBuilder<T>.() -> Unit) = set(toName(), DataTreeBuilder(type).apply(block))
+    public infix fun String.put(block: DataTreeBuilder<T>.() -> Unit): Unit = set(toName(), DataTreeBuilder(type).apply(block))
 
 
     /**
      * Update data with given node data and meta with node meta.
      */
-    fun update(node: DataNode<T>) {
+    public fun update(node: DataNode<T>) {
         node.dataSequence().forEach {
             //TODO check if the place is occupied
             this[it.first] = it.second
@@ -225,13 +225,13 @@ class DataTreeBuilder<T : Any>(val type: KClass<out T>) {
         meta.update(node.meta)
     }
 
-    fun meta(block: MetaBuilder.() -> Unit) = meta.apply(block)
+    public fun meta(block: MetaBuilder.() -> Unit): MetaBuilder = meta.apply(block)
 
-    fun meta(meta: Meta) {
+    public fun meta(meta: Meta) {
         this.meta = meta.builder()
     }
 
-    fun build(): DataTree<T> {
+    public fun build(): DataTree<T> {
         val resMap = map.mapValues { (_, value) ->
             when (value) {
                 is DataTreeBuilderItem.Leaf -> DataItem.Leaf(value.value)
@@ -242,50 +242,50 @@ class DataTreeBuilder<T : Any>(val type: KClass<out T>) {
     }
 }
 
-fun <T : Any> DataTreeBuilder<T>.datum(name: Name, data: Data<T>) {
+public fun <T : Any> DataTreeBuilder<T>.datum(name: Name, data: Data<T>) {
     this[name] = data
 }
 
-fun <T : Any> DataTreeBuilder<T>.datum(name: String, data: Data<T>) {
+public fun <T : Any> DataTreeBuilder<T>.datum(name: String, data: Data<T>) {
     this[name.toName()] = data
 }
 
-fun <T : Any> DataTreeBuilder<T>.static(name: Name, data: T, meta: Meta = Meta.EMPTY) {
+public fun <T : Any> DataTreeBuilder<T>.static(name: Name, data: T, meta: Meta = Meta.EMPTY) {
     this[name] = Data.static(data, meta)
 }
 
-fun <T : Any> DataTreeBuilder<T>.static(name: Name, data: T, block: MetaBuilder.() -> Unit = {}) {
+public fun <T : Any> DataTreeBuilder<T>.static(name: Name, data: T, block: MetaBuilder.() -> Unit = {}) {
     this[name] = Data.static(data, Meta(block))
 }
 
-fun <T : Any> DataTreeBuilder<T>.static(name: String, data: T, block: MetaBuilder.() -> Unit = {}) {
+public fun <T : Any> DataTreeBuilder<T>.static(name: String, data: T, block: MetaBuilder.() -> Unit = {}) {
     this[name.toName()] = Data.static(data, Meta(block))
 }
 
-fun <T : Any> DataTreeBuilder<T>.node(name: Name, node: DataNode<T>) {
+public fun <T : Any> DataTreeBuilder<T>.node(name: Name, node: DataNode<T>) {
     this[name] = node
 }
 
-fun <T : Any> DataTreeBuilder<T>.node(name: String, node: DataNode<T>) {
+public fun <T : Any> DataTreeBuilder<T>.node(name: String, node: DataNode<T>) {
     this[name.toName()] = node
 }
 
-inline fun <reified T : Any> DataTreeBuilder<T>.node(name: Name, noinline block: DataTreeBuilder<T>.() -> Unit) {
+public inline fun <reified T : Any> DataTreeBuilder<T>.node(name: Name, noinline block: DataTreeBuilder<T>.() -> Unit) {
     this[name] = DataNode(T::class, block)
 }
 
-inline fun <reified T : Any> DataTreeBuilder<T>.node(name: String, noinline block: DataTreeBuilder<T>.() -> Unit) {
+public inline fun <reified T : Any> DataTreeBuilder<T>.node(name: String, noinline block: DataTreeBuilder<T>.() -> Unit) {
     this[name.toName()] = DataNode(T::class, block)
 }
 
 /**
  * Generate a mutable builder from this node. Node content is not changed
  */
-fun <T : Any> DataNode<T>.builder(): DataTreeBuilder<T> = DataTreeBuilder(type).apply {
+public fun <T : Any> DataNode<T>.builder(): DataTreeBuilder<T> = DataTreeBuilder(type).apply {
     dataSequence().forEach { (name, data) -> this[name] = data }
 }
 
-fun <T : Any> DataNode<T>.filter(predicate: (Name, Data<T>) -> Boolean): DataNode<T> = DataNode.invoke(type) {
+public fun <T : Any> DataNode<T>.filter(predicate: (Name, Data<T>) -> Boolean): DataNode<T> = DataNode.invoke(type) {
     dataSequence().forEach { (name, data) ->
         if (predicate(name, data)) {
             this[name] = data
@@ -293,4 +293,4 @@ fun <T : Any> DataNode<T>.filter(predicate: (Name, Data<T>) -> Boolean): DataNod
     }
 }
 
-fun <T : Any> DataNode<T>.first(): Data<T>? = dataSequence().first().second
\ No newline at end of file
+public fun <T : Any> DataNode<T>.first(): Data<T>? = dataSequence().first().second
\ No newline at end of file
diff --git a/dataforge-data/src/commonMain/kotlin/hep/dataforge/data/Goal.kt b/dataforge-data/src/commonMain/kotlin/hep/dataforge/data/Goal.kt
index 8c0eeec7..e5050d22 100644
--- a/dataforge-data/src/commonMain/kotlin/hep/dataforge/data/Goal.kt
+++ b/dataforge-data/src/commonMain/kotlin/hep/dataforge/data/Goal.kt
@@ -1,37 +1,36 @@
 package hep.dataforge.data
 
+import hep.dataforge.meta.DFExperimental
 import kotlinx.coroutines.*
 import kotlin.coroutines.CoroutineContext
 import kotlin.coroutines.EmptyCoroutineContext
 
-interface Goal<out T> {
-    val dependencies: Collection<Goal<*>>
+public interface Goal<out T> {
+    public val dependencies: Collection<Goal<*>>
     /**
      * Returns current running coroutine if the goal is started
      */
-    val result: Deferred<T>?
+    public val result: Deferred<T>?
 
     /**
      * Get ongoing computation or start a new one.
      * Does not guarantee thread safety. In case of multi-thread access, could create orphan computations.
      */
-    fun CoroutineScope.startAsync(): Deferred<T>
+    public fun CoroutineScope.startAsync(): Deferred<T>
 
     /**
      * Reset the computation
      */
-    fun reset()
+    public fun reset()
 
-    companion object {
-
-    }
+    public companion object
 }
 
-suspend fun <T> Goal<T>.await(): T = coroutineScope { startAsync().await() }
+public suspend fun <T> Goal<T>.await(): T = coroutineScope { startAsync().await() }
 
-val Goal<*>.isComplete get() = result?.isCompleted ?: false
+public val Goal<*>.isComplete: Boolean get() = result?.isCompleted ?: false
 
-open class StaticGoal<T>(val value: T) : Goal<T> {
+public open class StaticGoal<T>(public val value: T) : Goal<T> {
     override val dependencies: Collection<Goal<*>> get() = emptyList()
     override val result: Deferred<T> = CompletableDeferred(value)
 
@@ -42,10 +41,10 @@ open class StaticGoal<T>(val value: T) : Goal<T> {
     }
 }
 
-open class DynamicGoal<T>(
-    val coroutineContext: CoroutineContext = EmptyCoroutineContext,
+public open class DynamicGoal<T>(
+    private val coroutineContext: CoroutineContext = EmptyCoroutineContext,
     override val dependencies: Collection<Goal<*>> = emptyList(),
-    val block: suspend CoroutineScope.() -> T
+    public val block: suspend CoroutineScope.() -> T
 ) : Goal<T> {
 
     final override var result: Deferred<T>? = null
@@ -55,6 +54,7 @@ open class DynamicGoal<T>(
      * Get ongoing computation or start a new one.
      * Does not guarantee thread safety. In case of multi-thread access, could create orphan computations.
      */
+    @DFExperimental
     override fun CoroutineScope.startAsync(): Deferred<T> {
         val startedDependencies = this@DynamicGoal.dependencies.map { goal ->
             goal.run { startAsync() }
@@ -82,7 +82,7 @@ open class DynamicGoal<T>(
 /**
  * Create a one-to-one goal based on existing goal
  */
-fun <T, R> Goal<T>.map(
+public fun <T, R> Goal<T>.map(
     coroutineContext: CoroutineContext = EmptyCoroutineContext,
     block: suspend CoroutineScope.(T) -> R
 ): Goal<R> = DynamicGoal(coroutineContext, listOf(this)) {
@@ -92,7 +92,7 @@ fun <T, R> Goal<T>.map(
 /**
  * Create a joining goal.
  */
-fun <T, R> Collection<Goal<T>>.reduce(
+public fun <T, R> Collection<Goal<T>>.reduce(
     coroutineContext: CoroutineContext = EmptyCoroutineContext,
     block: suspend CoroutineScope.(Collection<T>) -> R
 ): Goal<R> = DynamicGoal(coroutineContext, this) {
@@ -105,7 +105,7 @@ fun <T, R> Collection<Goal<T>>.reduce(
  * @param T type of the input goal
  * @param R type of the result goal
  */
-fun <K, T, R> Map<K, Goal<T>>.reduce(
+public fun <K, T, R> Map<K, Goal<T>>.reduce(
     coroutineContext: CoroutineContext = EmptyCoroutineContext,
     block: suspend CoroutineScope.(Map<K, T>) -> R
 ): Goal<R> = DynamicGoal(coroutineContext, this.values) {
diff --git a/dataforge-data/src/commonMain/kotlin/hep/dataforge/data/GroupRule.kt b/dataforge-data/src/commonMain/kotlin/hep/dataforge/data/GroupRule.kt
index 5cfc55e8..0a5de778 100644
--- a/dataforge-data/src/commonMain/kotlin/hep/dataforge/data/GroupRule.kt
+++ b/dataforge-data/src/commonMain/kotlin/hep/dataforge/data/GroupRule.kt
@@ -19,10 +19,10 @@ import hep.dataforge.meta.Meta
 import hep.dataforge.meta.get
 import hep.dataforge.meta.string
 
-interface GroupRule {
-    operator fun <T : Any> invoke(node: DataNode<T>): Map<String, DataNode<T>>
+public interface GroupRule {
+    public operator fun <T : Any> invoke(node: DataNode<T>): Map<String, DataNode<T>>
 
-    companion object{
+    public companion object{
         /**
          * Create grouping rule that creates groups for different values of value
          * field with name [key]
@@ -31,7 +31,7 @@ interface GroupRule {
          * @param defaultTagValue
          * @return
          */
-        fun byValue(key: String, defaultTagValue: String): GroupRule = object :
+        public fun byValue(key: String, defaultTagValue: String): GroupRule = object :
             GroupRule {
             override fun <T : Any> invoke(node: DataNode<T>): Map<String, DataNode<T>> {
                 val map = HashMap<String, DataTreeBuilder<T>>()
@@ -52,7 +52,7 @@ interface GroupRule {
 //        def = "default",
 //        info = "Default value which should be used for content in which the grouping value is not presented"
 //    )
-        fun byMeta(config: Meta): GroupRule {
+        public fun byMeta(config: Meta): GroupRule {
             //TODO expand grouping options
             return config["byValue"]?.string?.let {
                 byValue(
diff --git a/dataforge-data/src/commonMain/kotlin/hep/dataforge/data/MapAction.kt b/dataforge-data/src/commonMain/kotlin/hep/dataforge/data/MapAction.kt
index 61598349..e5504530 100644
--- a/dataforge-data/src/commonMain/kotlin/hep/dataforge/data/MapAction.kt
+++ b/dataforge-data/src/commonMain/kotlin/hep/dataforge/data/MapAction.kt
@@ -7,32 +7,31 @@ import kotlin.reflect.KClass
 /**
  * Action environment includes data name, data meta and action configuration meta
  */
-data class ActionEnv(
+public data class ActionEnv(
     val name: Name,
     val meta: Meta,
     val actionMeta: Meta
 )
 
-
 /**
  * Action environment
  */
 @DFBuilder
-class MapActionBuilder<T, R>(var name: Name, var meta: MetaBuilder, val actionMeta: Meta) {
-    lateinit var result: suspend ActionEnv.(T) -> R
+public class MapActionBuilder<T, R>(public var name: Name, public var meta: MetaBuilder, public val actionMeta: Meta) {
+    public lateinit var result: suspend ActionEnv.(T) -> R
 
     /**
      * Calculate the result of goal
      */
-    fun result(f: suspend ActionEnv.(T) -> R) {
+    public fun result(f: suspend ActionEnv.(T) -> R) {
         result = f;
     }
 }
 
 
-class MapAction<T : Any, out R : Any>(
-    val inputType: KClass<T>,
-    val outputType: KClass<out R>,
+public class MapAction<T : Any, out R : Any>(
+    public val inputType: KClass<T>,
+    public val outputType: KClass<out R>,
     private val block: MapActionBuilder<T, R>.() -> Unit
 ) : Action<T, R> {
 
@@ -67,7 +66,7 @@ class MapAction<T : Any, out R : Any>(
     }
 }
 
-inline fun <reified T : Any, reified R : Any> DataNode<T>.map(
+public inline fun <reified T : Any, reified R : Any> DataNode<T>.map(
     meta: Meta,
     noinline action: MapActionBuilder<in T, out R>.() -> Unit
 ): DataNode<R> = MapAction(T::class, R::class, action).invoke(this, meta)
diff --git a/dataforge-data/src/commonMain/kotlin/hep/dataforge/data/ReduceAction.kt b/dataforge-data/src/commonMain/kotlin/hep/dataforge/data/ReduceAction.kt
index 0efb5506..a0227af9 100644
--- a/dataforge-data/src/commonMain/kotlin/hep/dataforge/data/ReduceAction.kt
+++ b/dataforge-data/src/commonMain/kotlin/hep/dataforge/data/ReduceAction.kt
@@ -7,25 +7,25 @@ import hep.dataforge.names.toName
 import kotlin.reflect.KClass
 
 
-class JoinGroup<T : Any, R : Any>(var name: String, internal val node: DataNode<T>) {
+public class JoinGroup<T : Any, R : Any>(public var name: String, internal val node: DataNode<T>) {
 
-    var meta: MetaBuilder = MetaBuilder()
+    public var meta: MetaBuilder = MetaBuilder()
 
-    lateinit var result: suspend ActionEnv.(Map<Name, T>) -> R
+    public lateinit var result: suspend ActionEnv.(Map<Name, T>) -> R
 
-    fun result(f: suspend ActionEnv.(Map<Name, T>) -> R) {
+    public fun result(f: suspend ActionEnv.(Map<Name, T>) -> R) {
         this.result = f;
     }
 
 }
 
-class ReduceGroupBuilder<T : Any, R : Any>(val actionMeta: Meta) {
+public class ReduceGroupBuilder<T : Any, R : Any>(public val actionMeta: Meta) {
     private val groupRules: MutableList<(DataNode<T>) -> List<JoinGroup<T, R>>> = ArrayList();
 
     /**
      * introduce grouping by value name
      */
-    fun byValue(tag: String, defaultTag: String = "@default", action: JoinGroup<T, R>.() -> Unit) {
+    public fun byValue(tag: String, defaultTag: String = "@default", action: JoinGroup<T, R>.() -> Unit) {
         groupRules += { node ->
             GroupRule.byValue(tag, defaultTag).invoke(node).map {
                 JoinGroup<T, R>(it.key, it.value).apply(action)
@@ -36,7 +36,7 @@ class ReduceGroupBuilder<T : Any, R : Any>(val actionMeta: Meta) {
     /**
      * Add a single fixed group to grouping rules
      */
-    fun group(groupName: String, filter: DataFilter, action: JoinGroup<T, R>.() -> Unit) {
+    public fun group(groupName: String, filter: DataFilter, action: JoinGroup<T, R>.() -> Unit) {
         groupRules += { node ->
             listOf(
                 JoinGroup<T, R>(groupName, node.filter(filter)).apply(action)
@@ -44,7 +44,7 @@ class ReduceGroupBuilder<T : Any, R : Any>(val actionMeta: Meta) {
         }
     }
 
-    fun group(groupName: String, filter: (Name, Data<T>) -> Boolean, action: JoinGroup<T, R>.() -> Unit) {
+    public fun group(groupName: String, filter: (Name, Data<T>) -> Boolean, action: JoinGroup<T, R>.() -> Unit) {
         groupRules += { node ->
             listOf(
                 JoinGroup<T, R>(groupName, node.filter(filter)).apply(action)
@@ -55,7 +55,7 @@ class ReduceGroupBuilder<T : Any, R : Any>(val actionMeta: Meta) {
     /**
      * Apply transformation to the whole node
      */
-    fun result(resultName: String, f: suspend ActionEnv.(Map<Name, T>) -> R) {
+    public fun result(resultName: String, f: suspend ActionEnv.(Map<Name, T>) -> R) {
         groupRules += { node ->
             listOf(JoinGroup<T, R>(resultName, node).apply { result(f) })
         }
@@ -71,9 +71,9 @@ class ReduceGroupBuilder<T : Any, R : Any>(val actionMeta: Meta) {
 /**
  * The same rules as for KPipe
  */
-class ReduceAction<T : Any, R : Any>(
-    val inputType: KClass<T>,
-    val outputType: KClass<out R>,
+public class ReduceAction<T : Any, R : Any>(
+    public val inputType: KClass<T>,
+    public val outputType: KClass<out R>,
     private val action: ReduceGroupBuilder<T, R>.() -> Unit
 ) : Action<T, R> {
 
@@ -104,4 +104,4 @@ class ReduceAction<T : Any, R : Any>(
     }
 }
 
-operator fun <T> Map<Name, T>.get(name: String) = get(name.toName())
+public operator fun <T> Map<Name, T>.get(name: String): T? = get(name.toName())
diff --git a/dataforge-data/src/commonMain/kotlin/hep/dataforge/data/SplitAction.kt b/dataforge-data/src/commonMain/kotlin/hep/dataforge/data/SplitAction.kt
index dc29394c..731a9403 100644
--- a/dataforge-data/src/commonMain/kotlin/hep/dataforge/data/SplitAction.kt
+++ b/dataforge-data/src/commonMain/kotlin/hep/dataforge/data/SplitAction.kt
@@ -10,16 +10,16 @@ import kotlin.collections.set
 import kotlin.reflect.KClass
 
 
-class FragmentRule<T : Any, R : Any>(val name: Name, var meta: MetaBuilder) {
-    lateinit var result: suspend (T) -> R
+public class FragmentRule<T : Any, R : Any>(public val name: Name, public var meta: MetaBuilder) {
+    public lateinit var result: suspend (T) -> R
 
-    fun result(f: suspend (T) -> R) {
+    public fun result(f: suspend (T) -> R) {
         result = f;
     }
 }
 
 
-class SplitBuilder<T : Any, R : Any>(val name: Name, val meta: Meta) {
+public class SplitBuilder<T : Any, R : Any>(public val name: Name, public val meta: Meta) {
     internal val fragments: MutableMap<Name, FragmentRule<T, R>.() -> Unit> = HashMap()
 
     /**
@@ -27,14 +27,14 @@ class SplitBuilder<T : Any, R : Any>(val name: Name, val meta: Meta) {
      * @param name the name of a fragment
      * @param rule the rule to transform fragment name and meta using
      */
-    fun fragment(name: String, rule: FragmentRule<T, R>.() -> Unit) {
+    public fun fragment(name: String, rule: FragmentRule<T, R>.() -> Unit) {
         fragments[name.toName()] = rule
     }
 }
 
-class SplitAction<T : Any, R : Any>(
-    val inputType: KClass<T>,
-    val outputType: KClass<out R>,
+public class SplitAction<T : Any, R : Any>(
+    public val inputType: KClass<T>,
+    public val outputType: KClass<out R>,
     private val action: SplitBuilder<T, R>.() -> Unit
 ) : Action<T, R> {
 
diff --git a/dataforge-data/src/commonMain/kotlin/hep/dataforge/data/dataCast.kt b/dataforge-data/src/commonMain/kotlin/hep/dataforge/data/dataCast.kt
index 21301dd4..26563bc8 100644
--- a/dataforge-data/src/commonMain/kotlin/hep/dataforge/data/dataCast.kt
+++ b/dataforge-data/src/commonMain/kotlin/hep/dataforge/data/dataCast.kt
@@ -6,7 +6,7 @@ import kotlinx.coroutines.CoroutineScope
 import kotlinx.coroutines.Deferred
 import kotlin.reflect.KClass
 
-fun <R : Any, T : R> Data<T>.upcast(type: KClass<out R>): Data<R> {
+public fun <R : Any, T : R> Data<T>.upcast(type: KClass<out R>): Data<R> {
     return object : Data<R> by this {
         override val type: KClass<out R> = type
     }
@@ -15,19 +15,19 @@ fun <R : Any, T : R> Data<T>.upcast(type: KClass<out R>): Data<R> {
 /**
  * Safe upcast a [Data] to a supertype
  */
-inline fun <reified R : Any, T : R> Data<T>.upcast(): Data<R> = upcast(R::class)
+public inline fun <reified R : Any, T : R> Data<T>.upcast(): Data<R> = upcast(R::class)
 
 /**
  * Check if node could be safely cast to given class
  */
-expect fun <R : Any> DataNode<*>.canCast(type: KClass<out R>): Boolean
+internal expect fun <R : Any> DataNode<*>.canCast(type: KClass<out R>): Boolean
 
 /**
  * Check if data could be safely cast to given class
  */
-expect fun <R : Any> Data<*>.canCast(type: KClass<out R>): Boolean
+internal expect fun <R : Any> Data<*>.canCast(type: KClass<out R>): Boolean
 
-fun <R : Any> DataItem<*>.canCast(type: KClass<out R>): Boolean = when (this) {
+public fun <R : Any> DataItem<*>.canCast(type: KClass<out R>): Boolean = when (this) {
     is DataItem.Node -> node.canCast(type)
     is DataItem.Leaf -> data.canCast(type)
 }
@@ -36,7 +36,7 @@ fun <R : Any> DataItem<*>.canCast(type: KClass<out R>): Boolean = when (this) {
  * Unsafe cast of data node
  */
 @Suppress("UNCHECKED_CAST")
-fun <R : Any> Data<*>.cast(type: KClass<out R>): Data<R> {
+public fun <R : Any> Data<*>.cast(type: KClass<out R>): Data<R> {
     return object : Data<R> {
         override val meta: Meta get() = this@cast.meta
         override val dependencies: Collection<Goal<*>> get() = this@cast.dependencies
@@ -47,10 +47,10 @@ fun <R : Any> Data<*>.cast(type: KClass<out R>): Data<R> {
     }
 }
 
-inline fun <reified R : Any> Data<*>.cast(): Data<R> = cast(R::class)
+public inline fun <reified R : Any> Data<*>.cast(): Data<R> = cast(R::class)
 
 @Suppress("UNCHECKED_CAST")
-fun <R : Any> DataNode<*>.cast(type: KClass<out R>): DataNode<R> {
+public fun <R : Any> DataNode<*>.cast(type: KClass<out R>): DataNode<R> {
     return object : DataNode<R> {
         override val meta: Meta get() = this@cast.meta
         override val type: KClass<out R> = type
@@ -58,12 +58,12 @@ fun <R : Any> DataNode<*>.cast(type: KClass<out R>): DataNode<R> {
     }
 }
 
-inline fun <reified R : Any> DataNode<*>.cast(): DataNode<R> = cast(R::class)
+public inline fun <reified R : Any> DataNode<*>.cast(): DataNode<R> = cast(R::class)
 
 /**
  * Check that node is compatible with given type meaning that each element could be cast to the type
  */
-fun <T : Any> DataNode<*>.ensureType(type: KClass<out T>) {
+public fun <T : Any> DataNode<*>.ensureType(type: KClass<out T>) {
     if (!canCast(type)) {
         error("$type expected, but $type received")
     }
diff --git a/dataforge-data/src/jsMain/kotlin/hep/dataforge/data/dataJS.kt b/dataforge-data/src/jsMain/kotlin/hep/dataforge/data/dataJS.kt
index 54148bc5..0257b85a 100644
--- a/dataforge-data/src/jsMain/kotlin/hep/dataforge/data/dataJS.kt
+++ b/dataforge-data/src/jsMain/kotlin/hep/dataforge/data/dataJS.kt
@@ -5,12 +5,10 @@ import kotlin.reflect.KClass
 /**
  * Check that node is compatible with given type meaning that each element could be cast to the type
  */
-actual fun <R : Any> DataNode<*>.canCast(type: KClass<out R>): Boolean {
-    //Not supported in js yet
-    return true
+internal actual fun <R : Any> DataNode<*>.canCast(type: KClass<out R>): Boolean {
+    return this.type == type
 }
 
-actual fun <R : Any> Data<*>.canCast(type: KClass<out R>): Boolean {
-    //Not supported in js yet
-    return true
+internal actual fun <R : Any> Data<*>.canCast(type: KClass<out R>): Boolean {
+    return this.type == type
 }
diff --git a/dataforge-data/src/jvmMain/kotlin/hep/dataforge/data/TypeFilteredDataNode.kt b/dataforge-data/src/jvmMain/kotlin/hep/dataforge/data/TypeFilteredDataNode.kt
index 3590679c..b67becff 100644
--- a/dataforge-data/src/jvmMain/kotlin/hep/dataforge/data/TypeFilteredDataNode.kt
+++ b/dataforge-data/src/jvmMain/kotlin/hep/dataforge/data/TypeFilteredDataNode.kt
@@ -8,7 +8,7 @@ import kotlin.reflect.KClass
 /**
  * A zero-copy data node wrapper that returns only children with appropriate type.
  */
-class TypeFilteredDataNode<out T : Any>(val origin: DataNode<*>, override val type: KClass<out T>) : DataNode<T> {
+public class TypeFilteredDataNode<out T : Any>(public val origin: DataNode<*>, override val type: KClass<out T>) : DataNode<T> {
     override val meta: Meta get() = origin.meta
     override val items: Map<NameToken, DataItem<T>> by lazy {
         origin.items.mapNotNull { (key, item) ->
diff --git a/dataforge-data/src/jvmMain/kotlin/hep/dataforge/data/dataJVM.kt b/dataforge-data/src/jvmMain/kotlin/hep/dataforge/data/dataJVM.kt
index f354c2f7..6f758dae 100644
--- a/dataforge-data/src/jvmMain/kotlin/hep/dataforge/data/dataJVM.kt
+++ b/dataforge-data/src/jvmMain/kotlin/hep/dataforge/data/dataJVM.kt
@@ -3,33 +3,32 @@ package hep.dataforge.data
 import kotlinx.coroutines.runBlocking
 import kotlin.reflect.KClass
 import kotlin.reflect.full.isSubclassOf
-import kotlin.reflect.full.isSuperclassOf
 
 /**
  * Block the thread and get data content
  */
-fun <T : Any> Data<T>.get(): T = runBlocking { await() }
+public fun <T : Any> Data<T>.get(): T = runBlocking { await() }
 
 /**
  * Check that node is compatible with given type meaning that each element could be cast to the type
  */
-actual fun <R : Any> DataNode<*>.canCast(type: KClass<out R>): Boolean =
-    type.isSuperclassOf(type)
+internal actual fun <R : Any> DataNode<*>.canCast(type: KClass<out R>): Boolean =
+    type.isSubclassOf(this.type)
 
-actual fun <R : Any> Data<*>.canCast(type: KClass<out R>): Boolean =
+internal actual fun <R : Any> Data<*>.canCast(type: KClass<out R>): Boolean =
     this.type.isSubclassOf(type)
 
 /**
  * Cast the node to given type if the cast is possible or return null
  */
-fun <R : Any> Data<*>.filterIsInstance(type: KClass<out R>): Data<R>? =
+public fun <R : Any> Data<*>.filterIsInstance(type: KClass<out R>): Data<R>? =
     if (canCast(type)) cast(type) else null
 
 /**
  * Filter a node by data and node type. Resulting node and its subnodes is guaranteed to have border type [type],
  * but could contain empty nodes
  */
-fun <R : Any> DataNode<*>.filterIsInstance(type: KClass<out R>): DataNode<R> {
+public fun <R : Any> DataNode<*>.filterIsInstance(type: KClass<out R>): DataNode<R> {
     return when {
         canCast(type) -> cast(type)
         this is TypeFilteredDataNode -> origin.filterIsInstance(type)
@@ -40,10 +39,10 @@ fun <R : Any> DataNode<*>.filterIsInstance(type: KClass<out R>): DataNode<R> {
 /**
  * Filter all elements of given data item that could be cast to given type. If no elements are available, return null.
  */
-fun <R : Any> DataItem<*>?.filterIsInstance(type: KClass<out R>): DataItem<R>? = when (this) {
+public fun <R : Any> DataItem<*>?.filterIsInstance(type: KClass<out R>): DataItem<R>? = when (this) {
     null -> null
     is DataItem.Node -> DataItem.Node(this.node.filterIsInstance(type))
     is DataItem.Leaf -> this.data.filterIsInstance(type)?.let { DataItem.Leaf(it) }
 }
 
-inline fun <reified R : Any> DataItem<*>?.filterIsInstance(): DataItem<R>? = this@filterIsInstance.filterIsInstance(R::class)
\ No newline at end of file
+public inline fun <reified R : Any> DataItem<*>?.filterIsInstance(): DataItem<R>? = this@filterIsInstance.filterIsInstance(R::class)
\ No newline at end of file
diff --git a/dataforge-data/src/nativeMain/kotlin/hep/dataforge/data/dataNative.kt b/dataforge-data/src/nativeMain/kotlin/hep/dataforge/data/dataNative.kt
new file mode 100644
index 00000000..fe770f88
--- /dev/null
+++ b/dataforge-data/src/nativeMain/kotlin/hep/dataforge/data/dataNative.kt
@@ -0,0 +1,14 @@
+package hep.dataforge.data
+
+import kotlin.reflect.KClass
+
+/**
+ * Check that node is compatible with given type meaning that each element could be cast to the type
+ */
+internal actual fun <R : Any> DataNode<*>.canCast(type: KClass<out R>): Boolean {
+    return this.type == type
+}
+
+internal actual fun <R : Any> Data<*>.canCast(type: KClass<out R>): Boolean {
+    return this.type == type
+}
\ No newline at end of file
diff --git a/dataforge-io/api/dataforge-io.api b/dataforge-io/api/dataforge-io.api
new file mode 100644
index 00000000..1b8f876b
--- /dev/null
+++ b/dataforge-io/api/dataforge-io.api
@@ -0,0 +1,469 @@
+public final class hep/dataforge/io/BinaryMetaFormat : hep/dataforge/io/MetaFormat, hep/dataforge/io/MetaFormatFactory {
+	public static final field INSTANCE Lhep/dataforge/io/BinaryMetaFormat;
+	public fun getKey ()S
+	public fun getName ()Lhep/dataforge/names/Name;
+	public fun getShortName ()Ljava/lang/String;
+	public fun getType ()Lkotlin/reflect/KClass;
+	public fun invoke (Lhep/dataforge/meta/Meta;Lhep/dataforge/context/Context;)Lhep/dataforge/io/MetaFormat;
+	public synthetic fun invoke (Lhep/dataforge/meta/Meta;Lhep/dataforge/context/Context;)Ljava/lang/Object;
+	public fun readMeta (Lkotlinx/io/Input;Lhep/dataforge/meta/descriptors/NodeDescriptor;)Lhep/dataforge/meta/Meta;
+	public final fun readMetaItem (Lkotlinx/io/Input;)Lhep/dataforge/meta/MetaItem;
+	public fun readObject (Lkotlinx/io/Input;)Lhep/dataforge/meta/Meta;
+	public synthetic fun readObject (Lkotlinx/io/Input;)Ljava/lang/Object;
+	public fun toMeta ()Lhep/dataforge/meta/Meta;
+	public fun writeMeta (Lkotlinx/io/Output;Lhep/dataforge/meta/Meta;Lhep/dataforge/meta/descriptors/NodeDescriptor;)V
+	public fun writeObject (Lkotlinx/io/Output;Lhep/dataforge/meta/Meta;)V
+	public synthetic fun writeObject (Lkotlinx/io/Output;Ljava/lang/Object;)V
+	public final fun writeValue (Lkotlinx/io/Output;Lhep/dataforge/values/Value;)V
+}
+
+public final class hep/dataforge/io/BinaryView : kotlinx/io/Binary {
+	public fun <init> (Lkotlinx/io/Binary;II)V
+	public fun getSize ()I
+	public fun read (IILkotlin/jvm/functions/Function1;)Ljava/lang/Object;
+}
+
+public abstract interface class hep/dataforge/io/Consumer {
+	public abstract fun consume (Lhep/dataforge/io/Envelope;)V
+}
+
+public final class hep/dataforge/io/DoubleIOFormat : hep/dataforge/io/IOFormat, hep/dataforge/io/IOFormatFactory {
+	public static final field INSTANCE Lhep/dataforge/io/DoubleIOFormat;
+	public fun getName ()Lhep/dataforge/names/Name;
+	public fun getType ()Lkotlin/reflect/KClass;
+	public fun invoke (Lhep/dataforge/meta/Meta;Lhep/dataforge/context/Context;)Lhep/dataforge/io/IOFormat;
+	public synthetic fun invoke (Lhep/dataforge/meta/Meta;Lhep/dataforge/context/Context;)Ljava/lang/Object;
+	public fun readObject (Lkotlinx/io/Input;)Ljava/lang/Double;
+	public synthetic fun readObject (Lkotlinx/io/Input;)Ljava/lang/Object;
+	public fun toMeta ()Lhep/dataforge/meta/Meta;
+	public fun writeObject (Lkotlinx/io/Output;D)V
+	public synthetic fun writeObject (Lkotlinx/io/Output;Ljava/lang/Object;)V
+}
+
+public abstract interface class hep/dataforge/io/Envelope {
+	public static final field Companion Lhep/dataforge/io/Envelope$Companion;
+	public abstract fun getData ()Lkotlinx/io/Binary;
+	public abstract fun getMeta ()Lhep/dataforge/meta/Meta;
+}
+
+public final class hep/dataforge/io/Envelope$Companion {
+	public final fun getENVELOPE_DATA_ID_KEY ()Lhep/dataforge/names/Name;
+	public final fun getENVELOPE_DATA_TYPE_KEY ()Lhep/dataforge/names/Name;
+	public final fun getENVELOPE_DESCRIPTION_KEY ()Lhep/dataforge/names/Name;
+	public final fun getENVELOPE_NAME_KEY ()Lhep/dataforge/names/Name;
+	public final fun getENVELOPE_NODE_KEY ()Lhep/dataforge/names/Name;
+	public final fun getENVELOPE_TYPE_KEY ()Lhep/dataforge/names/Name;
+	public final fun invoke (Lkotlin/jvm/functions/Function1;)Lhep/dataforge/io/Envelope;
+}
+
+public final class hep/dataforge/io/EnvelopeBuilder : hep/dataforge/io/Envelope {
+	public fun <init> ()V
+	public final fun data (Lkotlin/jvm/functions/Function1;)V
+	public fun getData ()Lkotlinx/io/Binary;
+	public final fun getDataID ()Ljava/lang/String;
+	public final fun getDataType ()Ljava/lang/String;
+	public final fun getDescription ()Ljava/lang/String;
+	public fun getMeta ()Lhep/dataforge/meta/Meta;
+	public final fun getName ()Ljava/lang/String;
+	public final fun getType ()Ljava/lang/String;
+	public final fun meta (Lkotlin/jvm/functions/Function1;)V
+	public final fun seal ()Lhep/dataforge/io/Envelope;
+	public fun setData (Lkotlinx/io/Binary;)V
+	public final fun setDataID (Ljava/lang/String;)V
+	public final fun setDataType (Ljava/lang/String;)V
+	public final fun setDescription (Ljava/lang/String;)V
+	public fun setMeta (Lhep/dataforge/meta/Meta;)V
+	public final fun setName (Ljava/lang/String;)V
+	public final fun setType (Ljava/lang/String;)V
+}
+
+public abstract interface class hep/dataforge/io/EnvelopeFormat : hep/dataforge/io/IOFormat {
+	public abstract fun getDefaultMetaFormat ()Lhep/dataforge/io/MetaFormatFactory;
+	public abstract fun readObject (Lkotlinx/io/Input;)Lhep/dataforge/io/Envelope;
+	public abstract fun readPartial (Lkotlinx/io/Input;)Lhep/dataforge/io/PartialEnvelope;
+	public abstract fun writeEnvelope (Lkotlinx/io/Output;Lhep/dataforge/io/Envelope;Lhep/dataforge/io/MetaFormatFactory;Lhep/dataforge/meta/Meta;)V
+	public abstract fun writeObject (Lkotlinx/io/Output;Lhep/dataforge/io/Envelope;)V
+}
+
+public final class hep/dataforge/io/EnvelopeFormat$DefaultImpls {
+	public static fun getDefaultMetaFormat (Lhep/dataforge/io/EnvelopeFormat;)Lhep/dataforge/io/MetaFormatFactory;
+	public static synthetic fun writeEnvelope$default (Lhep/dataforge/io/EnvelopeFormat;Lkotlinx/io/Output;Lhep/dataforge/io/Envelope;Lhep/dataforge/io/MetaFormatFactory;Lhep/dataforge/meta/Meta;ILjava/lang/Object;)V
+	public static fun writeObject (Lhep/dataforge/io/EnvelopeFormat;Lkotlinx/io/Output;Lhep/dataforge/io/Envelope;)V
+}
+
+public abstract interface class hep/dataforge/io/EnvelopeFormatFactory : hep/dataforge/io/EnvelopeFormat, hep/dataforge/io/IOFormatFactory {
+	public static final field Companion Lhep/dataforge/io/EnvelopeFormatFactory$Companion;
+	public static final field ENVELOPE_FORMAT_TYPE Ljava/lang/String;
+	public abstract fun getName ()Lhep/dataforge/names/Name;
+	public abstract fun getType ()Lkotlin/reflect/KClass;
+	public abstract fun invoke (Lhep/dataforge/meta/Meta;Lhep/dataforge/context/Context;)Lhep/dataforge/io/EnvelopeFormat;
+	public abstract fun peekFormat (Lhep/dataforge/io/IOPlugin;Lkotlinx/io/Input;)Lhep/dataforge/io/EnvelopeFormat;
+}
+
+public final class hep/dataforge/io/EnvelopeFormatFactory$Companion {
+	public static final field ENVELOPE_FORMAT_TYPE Ljava/lang/String;
+}
+
+public final class hep/dataforge/io/EnvelopeFormatFactory$DefaultImpls {
+	public static fun getDefaultMetaFormat (Lhep/dataforge/io/EnvelopeFormatFactory;)Lhep/dataforge/io/MetaFormatFactory;
+	public static fun getName (Lhep/dataforge/io/EnvelopeFormatFactory;)Lhep/dataforge/names/Name;
+	public static fun getType (Lhep/dataforge/io/EnvelopeFormatFactory;)Lkotlin/reflect/KClass;
+	public static fun toMeta (Lhep/dataforge/io/EnvelopeFormatFactory;)Lhep/dataforge/meta/Meta;
+	public static fun writeObject (Lhep/dataforge/io/EnvelopeFormatFactory;Lkotlinx/io/Output;Lhep/dataforge/io/Envelope;)V
+}
+
+public final class hep/dataforge/io/EnvelopeFormatKt {
+	public static final fun read (Lhep/dataforge/io/EnvelopeFormat;Lkotlinx/io/Input;)Lhep/dataforge/io/Envelope;
+}
+
+public final class hep/dataforge/io/EnvelopeKt {
+	public static final fun contentEquals (Lhep/dataforge/io/Envelope;Lhep/dataforge/io/Envelope;)Z
+	public static final fun dataEquals (Lhep/dataforge/io/Envelope;Lhep/dataforge/io/Envelope;)Z
+	public static final fun getDataID (Lhep/dataforge/io/Envelope;)Ljava/lang/String;
+	public static final fun getDataType (Lhep/dataforge/io/Envelope;)Ljava/lang/String;
+	public static final fun getDescription (Lhep/dataforge/io/Envelope;)Ljava/lang/String;
+	public static final fun getType (Lhep/dataforge/io/Envelope;)Ljava/lang/String;
+	public static final fun metaEquals (Lhep/dataforge/io/Envelope;Lhep/dataforge/io/Envelope;)Z
+	public static final fun withMetaLayers (Lhep/dataforge/io/Envelope;[Lhep/dataforge/meta/Meta;)Lhep/dataforge/io/Envelope;
+}
+
+public final class hep/dataforge/io/EnvelopePart {
+	public fun <init> (Lkotlinx/io/Binary;Lhep/dataforge/meta/Meta;)V
+	public final fun component1 ()Lkotlinx/io/Binary;
+	public final fun component2 ()Lhep/dataforge/meta/Meta;
+	public final fun copy (Lkotlinx/io/Binary;Lhep/dataforge/meta/Meta;)Lhep/dataforge/io/EnvelopePart;
+	public static synthetic fun copy$default (Lhep/dataforge/io/EnvelopePart;Lkotlinx/io/Binary;Lhep/dataforge/meta/Meta;ILjava/lang/Object;)Lhep/dataforge/io/EnvelopePart;
+	public fun equals (Ljava/lang/Object;)Z
+	public final fun getBinary ()Lkotlinx/io/Binary;
+	public final fun getDescription ()Lhep/dataforge/meta/Meta;
+	public fun hashCode ()I
+	public fun toString ()Ljava/lang/String;
+}
+
+public final class hep/dataforge/io/EnvelopePartsKt {
+	public static final fun envelope (Lhep/dataforge/io/EnvelopePart;Lhep/dataforge/io/EnvelopeFormat;)Lhep/dataforge/io/Envelope;
+	public static final fun envelope (Lhep/dataforge/io/EnvelopePart;Lhep/dataforge/io/IOPlugin;)Lhep/dataforge/io/Envelope;
+	public static final fun envelopes (Lhep/dataforge/io/EnvelopeBuilder;Ljava/util/List;Lhep/dataforge/io/EnvelopeFormat;Ljava/lang/String;)V
+	public static synthetic fun envelopes$default (Lhep/dataforge/io/EnvelopeBuilder;Ljava/util/List;Lhep/dataforge/io/EnvelopeFormat;Ljava/lang/String;ILjava/lang/Object;)V
+	public static final fun getName (Lhep/dataforge/io/EnvelopePart;)Ljava/lang/String;
+	public static final fun multipart (Lhep/dataforge/io/EnvelopeBuilder;Ljava/util/List;Ljava/lang/String;)V
+	public static synthetic fun multipart$default (Lhep/dataforge/io/EnvelopeBuilder;Ljava/util/List;Ljava/lang/String;ILjava/lang/Object;)V
+	public static final fun parts (Lhep/dataforge/io/Envelope;)Ljava/util/List;
+}
+
+public final class hep/dataforge/io/FileIOKt {
+	public static final fun append (Ljava/nio/file/Path;Lkotlin/jvm/functions/Function1;)V
+	public static final fun getDATA_FILE_NAME (Lhep/dataforge/io/IOPlugin$Companion;)Ljava/lang/String;
+	public static final fun getMETA_FILE_NAME (Lhep/dataforge/io/IOPlugin$Companion;)Ljava/lang/String;
+	public static final fun peekBinaryFormat (Lhep/dataforge/io/IOPlugin;Ljava/nio/file/Path;)Lhep/dataforge/io/EnvelopeFormat;
+	public static final fun read (Ljava/nio/file/Path;Lkotlin/jvm/functions/Function1;)Ljava/lang/Object;
+	public static final fun readEnvelope (Ljava/nio/file/Path;Lhep/dataforge/io/EnvelopeFormat;)Lhep/dataforge/io/Envelope;
+	public static final fun readEnvelopeFile (Lhep/dataforge/io/IOPlugin;Ljava/nio/file/Path;ZLkotlin/jvm/functions/Function2;)Lhep/dataforge/io/Envelope;
+	public static synthetic fun readEnvelopeFile$default (Lhep/dataforge/io/IOPlugin;Ljava/nio/file/Path;ZLkotlin/jvm/functions/Function2;ILjava/lang/Object;)Lhep/dataforge/io/Envelope;
+	public static final fun readMetaFile (Lhep/dataforge/io/IOPlugin;Ljava/nio/file/Path;Lhep/dataforge/io/MetaFormat;Lhep/dataforge/meta/descriptors/NodeDescriptor;)Lhep/dataforge/meta/Meta;
+	public static synthetic fun readMetaFile$default (Lhep/dataforge/io/IOPlugin;Ljava/nio/file/Path;Lhep/dataforge/io/MetaFormat;Lhep/dataforge/meta/descriptors/NodeDescriptor;ILjava/lang/Object;)Lhep/dataforge/meta/Meta;
+	public static final fun rewrite (Ljava/nio/file/Path;Lkotlin/jvm/functions/Function1;)V
+	public static final fun write (Ljava/nio/file/Path;Lkotlin/jvm/functions/Function1;)V
+	public static final fun writeEnvelopeDirectory (Lhep/dataforge/io/IOPlugin;Ljava/nio/file/Path;Lhep/dataforge/io/Envelope;Lhep/dataforge/io/MetaFormatFactory;)V
+	public static synthetic fun writeEnvelopeDirectory$default (Lhep/dataforge/io/IOPlugin;Ljava/nio/file/Path;Lhep/dataforge/io/Envelope;Lhep/dataforge/io/MetaFormatFactory;ILjava/lang/Object;)V
+	public static final fun writeEnvelopeFile (Lhep/dataforge/io/IOPlugin;Ljava/nio/file/Path;Lhep/dataforge/io/Envelope;Lhep/dataforge/io/EnvelopeFormat;Lhep/dataforge/io/MetaFormatFactory;)V
+	public static synthetic fun writeEnvelopeFile$default (Lhep/dataforge/io/IOPlugin;Ljava/nio/file/Path;Lhep/dataforge/io/Envelope;Lhep/dataforge/io/EnvelopeFormat;Lhep/dataforge/io/MetaFormatFactory;ILjava/lang/Object;)V
+	public static final fun writeMetaFile (Lhep/dataforge/io/IOPlugin;Ljava/nio/file/Path;Lhep/dataforge/meta/Meta;Lhep/dataforge/io/MetaFormatFactory;Lhep/dataforge/meta/descriptors/NodeDescriptor;)V
+	public static synthetic fun writeMetaFile$default (Lhep/dataforge/io/IOPlugin;Ljava/nio/file/Path;Lhep/dataforge/meta/Meta;Lhep/dataforge/io/MetaFormatFactory;Lhep/dataforge/meta/descriptors/NodeDescriptor;ILjava/lang/Object;)V
+	public static final fun writeToFile (Lhep/dataforge/io/IOFormat;Ljava/nio/file/Path;Ljava/lang/Object;)V
+}
+
+public abstract interface class hep/dataforge/io/IOFormat : hep/dataforge/meta/MetaRepr {
+	public static final field Companion Lhep/dataforge/io/IOFormat$Companion;
+	public abstract fun readObject (Lkotlinx/io/Input;)Ljava/lang/Object;
+	public abstract fun writeObject (Lkotlinx/io/Output;Ljava/lang/Object;)V
+}
+
+public final class hep/dataforge/io/IOFormat$Companion {
+	public final fun getMETA_KEY ()Lhep/dataforge/names/Name;
+	public final fun getNAME_KEY ()Lhep/dataforge/names/Name;
+}
+
+public abstract interface class hep/dataforge/io/IOFormatFactory : hep/dataforge/context/Factory, hep/dataforge/context/Named, hep/dataforge/meta/MetaRepr {
+	public static final field Companion Lhep/dataforge/io/IOFormatFactory$Companion;
+	public static final field IO_FORMAT_TYPE Ljava/lang/String;
+	public abstract fun getType ()Lkotlin/reflect/KClass;
+	public abstract fun toMeta ()Lhep/dataforge/meta/Meta;
+}
+
+public final class hep/dataforge/io/IOFormatFactory$Companion {
+	public static final field IO_FORMAT_TYPE Ljava/lang/String;
+}
+
+public final class hep/dataforge/io/IOFormatFactory$DefaultImpls {
+	public static fun toMeta (Lhep/dataforge/io/IOFormatFactory;)Lhep/dataforge/meta/Meta;
+}
+
+public final class hep/dataforge/io/IOFormatKt {
+	public static final fun fill (Lkotlinx/io/pool/ObjectPool;Lkotlin/jvm/functions/Function1;)Ljava/nio/ByteBuffer;
+	public static final fun readWith (Lkotlinx/io/Binary;Lhep/dataforge/io/IOFormat;)Ljava/lang/Object;
+	public static final fun readWith (Lkotlinx/io/Input;Lhep/dataforge/io/IOFormat;)Ljava/lang/Object;
+	public static final fun toBinary (Lhep/dataforge/io/IOFormat;Ljava/lang/Object;)Lkotlinx/io/Binary;
+	public static final fun writeWith (Lkotlinx/io/Output;Lhep/dataforge/io/IOFormat;Ljava/lang/Object;)V
+}
+
+public final class hep/dataforge/io/IOPlugin : hep/dataforge/context/AbstractPlugin {
+	public static final field Companion Lhep/dataforge/io/IOPlugin$Companion;
+	public fun <init> (Lhep/dataforge/meta/Meta;)V
+	public fun content (Ljava/lang/String;)Ljava/util/Map;
+	public final fun getEnvelopeFormatFactories ()Ljava/util/Collection;
+	public final fun getIoFormatFactories ()Ljava/util/Collection;
+	public final fun getMetaFormatFactories ()Ljava/util/Collection;
+	public fun getTag ()Lhep/dataforge/context/PluginTag;
+	public final fun resolveEnvelopeFormat (Lhep/dataforge/meta/MetaItem;)Lhep/dataforge/io/EnvelopeFormat;
+	public final fun resolveIOFormat (Lhep/dataforge/meta/MetaItem;Lkotlin/reflect/KClass;)Lhep/dataforge/io/IOFormat;
+	public final fun resolveMetaFormat (Ljava/lang/String;Lhep/dataforge/meta/Meta;)Lhep/dataforge/io/MetaFormat;
+	public final fun resolveMetaFormat (SLhep/dataforge/meta/Meta;)Lhep/dataforge/io/MetaFormat;
+	public static synthetic fun resolveMetaFormat$default (Lhep/dataforge/io/IOPlugin;Ljava/lang/String;Lhep/dataforge/meta/Meta;ILjava/lang/Object;)Lhep/dataforge/io/MetaFormat;
+	public static synthetic fun resolveMetaFormat$default (Lhep/dataforge/io/IOPlugin;SLhep/dataforge/meta/Meta;ILjava/lang/Object;)Lhep/dataforge/io/MetaFormat;
+}
+
+public final class hep/dataforge/io/IOPlugin$Companion : hep/dataforge/context/PluginFactory {
+	public final fun getDefaultEnvelopeFormats ()Ljava/util/List;
+	public final fun getDefaultMetaFormats ()Ljava/util/List;
+	public fun getTag ()Lhep/dataforge/context/PluginTag;
+	public fun getType ()Lkotlin/reflect/KClass;
+	public fun invoke (Lhep/dataforge/meta/Meta;Lhep/dataforge/context/Context;)Lhep/dataforge/io/IOPlugin;
+	public synthetic fun invoke (Lhep/dataforge/meta/Meta;Lhep/dataforge/context/Context;)Ljava/lang/Object;
+}
+
+public final class hep/dataforge/io/IOPluginKt {
+	public static final fun getIo (Lhep/dataforge/context/Context;)Lhep/dataforge/io/IOPlugin;
+}
+
+public final class hep/dataforge/io/IoMiscKt {
+	public static final fun Binary (ILkotlin/jvm/functions/Function1;)Lkotlinx/io/Binary;
+	public static synthetic fun Binary$default (ILkotlin/jvm/functions/Function1;ILjava/lang/Object;)Lkotlinx/io/Binary;
+	public static final fun buildByteArray (ILkotlin/jvm/functions/Function1;)[B
+	public static synthetic fun buildByteArray$default (ILkotlin/jvm/functions/Function1;ILjava/lang/Object;)[B
+	public static final fun get (Lkotlinx/io/Binary;Lkotlin/ranges/IntRange;)Lhep/dataforge/io/BinaryView;
+	public static final fun readRawString (Lkotlinx/io/Input;I)Ljava/lang/String;
+	public static final fun view (Lkotlinx/io/Binary;II)Lhep/dataforge/io/BinaryView;
+	public static final fun writeRawString (Lkotlinx/io/Output;Ljava/lang/String;)V
+}
+
+public final class hep/dataforge/io/JsonMetaFormat : hep/dataforge/io/MetaFormat {
+	public static final field Companion Lhep/dataforge/io/JsonMetaFormat$Companion;
+	public fun <init> ()V
+	public fun <init> (Lkotlinx/serialization/json/Json;)V
+	public synthetic fun <init> (Lkotlinx/serialization/json/Json;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
+	public fun readMeta (Lkotlinx/io/Input;Lhep/dataforge/meta/descriptors/NodeDescriptor;)Lhep/dataforge/meta/Meta;
+	public fun readObject (Lkotlinx/io/Input;)Lhep/dataforge/meta/Meta;
+	public synthetic fun readObject (Lkotlinx/io/Input;)Ljava/lang/Object;
+	public fun toMeta ()Lhep/dataforge/meta/Meta;
+	public fun writeMeta (Lkotlinx/io/Output;Lhep/dataforge/meta/Meta;Lhep/dataforge/meta/descriptors/NodeDescriptor;)V
+	public fun writeObject (Lkotlinx/io/Output;Lhep/dataforge/meta/Meta;)V
+	public synthetic fun writeObject (Lkotlinx/io/Output;Ljava/lang/Object;)V
+}
+
+public final class hep/dataforge/io/JsonMetaFormat$Companion : hep/dataforge/io/MetaFormatFactory {
+	public final fun getDEFAULT_JSON ()Lkotlinx/serialization/json/Json;
+	public fun getKey ()S
+	public fun getName ()Lhep/dataforge/names/Name;
+	public fun getShortName ()Ljava/lang/String;
+	public fun getType ()Lkotlin/reflect/KClass;
+	public fun invoke (Lhep/dataforge/meta/Meta;Lhep/dataforge/context/Context;)Lhep/dataforge/io/MetaFormat;
+	public synthetic fun invoke (Lhep/dataforge/meta/Meta;Lhep/dataforge/context/Context;)Ljava/lang/Object;
+	public fun readMeta (Lkotlinx/io/Input;Lhep/dataforge/meta/descriptors/NodeDescriptor;)Lhep/dataforge/meta/Meta;
+	public fun readObject (Lkotlinx/io/Input;)Lhep/dataforge/meta/Meta;
+	public synthetic fun readObject (Lkotlinx/io/Input;)Ljava/lang/Object;
+	public fun toMeta ()Lhep/dataforge/meta/Meta;
+	public fun writeMeta (Lkotlinx/io/Output;Lhep/dataforge/meta/Meta;Lhep/dataforge/meta/descriptors/NodeDescriptor;)V
+	public fun writeObject (Lkotlinx/io/Output;Lhep/dataforge/meta/Meta;)V
+	public synthetic fun writeObject (Lkotlinx/io/Output;Ljava/lang/Object;)V
+}
+
+public final class hep/dataforge/io/ListIOFormat : hep/dataforge/io/IOFormat {
+	public fun <init> (Lhep/dataforge/io/IOFormat;)V
+	public final fun getFormat ()Lhep/dataforge/io/IOFormat;
+	public synthetic fun readObject (Lkotlinx/io/Input;)Ljava/lang/Object;
+	public fun readObject (Lkotlinx/io/Input;)Ljava/util/List;
+	public fun toMeta ()Lhep/dataforge/meta/Meta;
+	public synthetic fun writeObject (Lkotlinx/io/Output;Ljava/lang/Object;)V
+	public fun writeObject (Lkotlinx/io/Output;Ljava/util/List;)V
+}
+
+public abstract interface class hep/dataforge/io/MetaFormat : hep/dataforge/io/IOFormat {
+	public abstract fun readMeta (Lkotlinx/io/Input;Lhep/dataforge/meta/descriptors/NodeDescriptor;)Lhep/dataforge/meta/Meta;
+	public abstract fun readObject (Lkotlinx/io/Input;)Lhep/dataforge/meta/Meta;
+	public abstract fun writeMeta (Lkotlinx/io/Output;Lhep/dataforge/meta/Meta;Lhep/dataforge/meta/descriptors/NodeDescriptor;)V
+	public abstract fun writeObject (Lkotlinx/io/Output;Lhep/dataforge/meta/Meta;)V
+}
+
+public final class hep/dataforge/io/MetaFormat$DefaultImpls {
+	public static synthetic fun readMeta$default (Lhep/dataforge/io/MetaFormat;Lkotlinx/io/Input;Lhep/dataforge/meta/descriptors/NodeDescriptor;ILjava/lang/Object;)Lhep/dataforge/meta/Meta;
+	public static fun readObject (Lhep/dataforge/io/MetaFormat;Lkotlinx/io/Input;)Lhep/dataforge/meta/Meta;
+	public static synthetic fun writeMeta$default (Lhep/dataforge/io/MetaFormat;Lkotlinx/io/Output;Lhep/dataforge/meta/Meta;Lhep/dataforge/meta/descriptors/NodeDescriptor;ILjava/lang/Object;)V
+	public static fun writeObject (Lhep/dataforge/io/MetaFormat;Lkotlinx/io/Output;Lhep/dataforge/meta/Meta;)V
+}
+
+public abstract interface class hep/dataforge/io/MetaFormatFactory : hep/dataforge/io/IOFormatFactory, hep/dataforge/io/MetaFormat {
+	public static final field Companion Lhep/dataforge/io/MetaFormatFactory$Companion;
+	public static final field META_FORMAT_TYPE Ljava/lang/String;
+	public abstract fun getKey ()S
+	public abstract fun getName ()Lhep/dataforge/names/Name;
+	public abstract fun getShortName ()Ljava/lang/String;
+	public abstract fun getType ()Lkotlin/reflect/KClass;
+	public abstract fun invoke (Lhep/dataforge/meta/Meta;Lhep/dataforge/context/Context;)Lhep/dataforge/io/MetaFormat;
+}
+
+public final class hep/dataforge/io/MetaFormatFactory$Companion {
+	public static final field META_FORMAT_TYPE Ljava/lang/String;
+}
+
+public final class hep/dataforge/io/MetaFormatFactory$DefaultImpls {
+	public static fun getKey (Lhep/dataforge/io/MetaFormatFactory;)S
+	public static fun getName (Lhep/dataforge/io/MetaFormatFactory;)Lhep/dataforge/names/Name;
+	public static fun getType (Lhep/dataforge/io/MetaFormatFactory;)Lkotlin/reflect/KClass;
+	public static fun readObject (Lhep/dataforge/io/MetaFormatFactory;Lkotlinx/io/Input;)Lhep/dataforge/meta/Meta;
+	public static fun toMeta (Lhep/dataforge/io/MetaFormatFactory;)Lhep/dataforge/meta/Meta;
+	public static fun writeObject (Lhep/dataforge/io/MetaFormatFactory;Lkotlinx/io/Output;Lhep/dataforge/meta/Meta;)V
+}
+
+public final class hep/dataforge/io/MetaFormatKt {
+	public static final fun parse (Lhep/dataforge/io/MetaFormat;Ljava/lang/String;)Lhep/dataforge/meta/Meta;
+	public static final fun parse (Lhep/dataforge/io/MetaFormatFactory;Ljava/lang/String;Lhep/dataforge/meta/Meta;)Lhep/dataforge/meta/Meta;
+	public static final fun toString (Lhep/dataforge/meta/Meta;Lhep/dataforge/io/MetaFormat;)Ljava/lang/String;
+	public static final fun toString (Lhep/dataforge/meta/Meta;Lhep/dataforge/io/MetaFormatFactory;)Ljava/lang/String;
+}
+
+public final class hep/dataforge/io/PartialEnvelope {
+	public synthetic fun <init> (Lhep/dataforge/meta/Meta;ILkotlin/ULong;Lkotlin/jvm/internal/DefaultConstructorMarker;)V
+	public final fun component1 ()Lhep/dataforge/meta/Meta;
+	public final fun component2-pVg5ArA ()I
+	public final fun component3-6VbMDqA ()Lkotlin/ULong;
+	public final fun copy-BMK4sig (Lhep/dataforge/meta/Meta;ILkotlin/ULong;)Lhep/dataforge/io/PartialEnvelope;
+	public static synthetic fun copy-BMK4sig$default (Lhep/dataforge/io/PartialEnvelope;Lhep/dataforge/meta/Meta;ILkotlin/ULong;ILjava/lang/Object;)Lhep/dataforge/io/PartialEnvelope;
+	public fun equals (Ljava/lang/Object;)Z
+	public final fun getDataOffset-pVg5ArA ()I
+	public final fun getDataSize-6VbMDqA ()Lkotlin/ULong;
+	public final fun getMeta ()Lhep/dataforge/meta/Meta;
+	public fun hashCode ()I
+	public fun toString ()Ljava/lang/String;
+}
+
+public final class hep/dataforge/io/ProxyEnvelope : hep/dataforge/io/Envelope {
+	public fun <init> (Lhep/dataforge/io/Envelope;[Lhep/dataforge/meta/Meta;)V
+	public fun getData ()Lkotlinx/io/Binary;
+	public fun getMeta ()Lhep/dataforge/meta/Laminate;
+	public synthetic fun getMeta ()Lhep/dataforge/meta/Meta;
+	public final fun getSource ()Lhep/dataforge/io/Envelope;
+}
+
+public abstract interface class hep/dataforge/io/Responder {
+	public abstract fun respond (Lhep/dataforge/io/Envelope;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
+}
+
+public final class hep/dataforge/io/SimpleEnvelope : hep/dataforge/io/Envelope {
+	public fun <init> (Lhep/dataforge/meta/Meta;Lkotlinx/io/Binary;)V
+	public fun getData ()Lkotlinx/io/Binary;
+	public fun getMeta ()Lhep/dataforge/meta/Meta;
+}
+
+public final class hep/dataforge/io/StreamsIOKt {
+	public static final fun read (Ljava/io/InputStream;ILkotlin/jvm/functions/Function1;)Ljava/lang/Object;
+	public static final fun read (Ljava/io/InputStream;Lkotlin/jvm/functions/Function1;)Ljava/lang/Object;
+	public static final fun readBlocking (Ljava/io/InputStream;Lkotlin/jvm/functions/Function1;)Ljava/lang/Object;
+	public static final fun write (Ljava/io/OutputStream;Lkotlin/jvm/functions/Function1;)V
+}
+
+public final class hep/dataforge/io/TaggedEnvelopeFormat : hep/dataforge/io/EnvelopeFormat {
+	public static final field Companion Lhep/dataforge/io/TaggedEnvelopeFormat$Companion;
+	public fun <init> (Lhep/dataforge/io/IOPlugin;Lhep/dataforge/io/TaggedEnvelopeFormat$VERSION;)V
+	public synthetic fun <init> (Lhep/dataforge/io/IOPlugin;Lhep/dataforge/io/TaggedEnvelopeFormat$VERSION;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
+	public fun getDefaultMetaFormat ()Lhep/dataforge/io/MetaFormatFactory;
+	public final fun getIo ()Lhep/dataforge/io/IOPlugin;
+	public final fun getVersion ()Lhep/dataforge/io/TaggedEnvelopeFormat$VERSION;
+	public fun readObject (Lkotlinx/io/Input;)Lhep/dataforge/io/Envelope;
+	public synthetic fun readObject (Lkotlinx/io/Input;)Ljava/lang/Object;
+	public fun readPartial (Lkotlinx/io/Input;)Lhep/dataforge/io/PartialEnvelope;
+	public fun toMeta ()Lhep/dataforge/meta/Meta;
+	public fun writeEnvelope (Lkotlinx/io/Output;Lhep/dataforge/io/Envelope;Lhep/dataforge/io/MetaFormatFactory;Lhep/dataforge/meta/Meta;)V
+	public fun writeObject (Lkotlinx/io/Output;Lhep/dataforge/io/Envelope;)V
+	public synthetic fun writeObject (Lkotlinx/io/Output;Ljava/lang/Object;)V
+}
+
+public final class hep/dataforge/io/TaggedEnvelopeFormat$Companion : hep/dataforge/io/EnvelopeFormatFactory {
+	public fun getDefaultMetaFormat ()Lhep/dataforge/io/MetaFormatFactory;
+	public fun getName ()Lhep/dataforge/names/Name;
+	public fun getType ()Lkotlin/reflect/KClass;
+	public fun invoke (Lhep/dataforge/meta/Meta;Lhep/dataforge/context/Context;)Lhep/dataforge/io/EnvelopeFormat;
+	public synthetic fun invoke (Lhep/dataforge/meta/Meta;Lhep/dataforge/context/Context;)Ljava/lang/Object;
+	public fun peekFormat (Lhep/dataforge/io/IOPlugin;Lkotlinx/io/Input;)Lhep/dataforge/io/EnvelopeFormat;
+	public fun readObject (Lkotlinx/io/Input;)Lhep/dataforge/io/Envelope;
+	public synthetic fun readObject (Lkotlinx/io/Input;)Ljava/lang/Object;
+	public fun readPartial (Lkotlinx/io/Input;)Lhep/dataforge/io/PartialEnvelope;
+	public fun toMeta ()Lhep/dataforge/meta/Meta;
+	public fun writeEnvelope (Lkotlinx/io/Output;Lhep/dataforge/io/Envelope;Lhep/dataforge/io/MetaFormatFactory;Lhep/dataforge/meta/Meta;)V
+	public fun writeObject (Lkotlinx/io/Output;Lhep/dataforge/io/Envelope;)V
+	public synthetic fun writeObject (Lkotlinx/io/Output;Ljava/lang/Object;)V
+}
+
+public final class hep/dataforge/io/TaggedEnvelopeFormat$VERSION : java/lang/Enum {
+	public static final field DF02 Lhep/dataforge/io/TaggedEnvelopeFormat$VERSION;
+	public static final field DF03 Lhep/dataforge/io/TaggedEnvelopeFormat$VERSION;
+	public final fun getTagSize-pVg5ArA ()I
+	public static fun valueOf (Ljava/lang/String;)Lhep/dataforge/io/TaggedEnvelopeFormat$VERSION;
+	public static fun values ()[Lhep/dataforge/io/TaggedEnvelopeFormat$VERSION;
+}
+
+public final class hep/dataforge/io/TaglessEnvelopeFormat : hep/dataforge/io/EnvelopeFormat {
+	public static final field Companion Lhep/dataforge/io/TaglessEnvelopeFormat$Companion;
+	public static final field DATA_LENGTH_PROPERTY Ljava/lang/String;
+	public static final field DATA_START_PROPERTY Ljava/lang/String;
+	public static final field DEFAULT_DATA_START Ljava/lang/String;
+	public static final field DEFAULT_META_START Ljava/lang/String;
+	public static final field META_LENGTH_PROPERTY Ljava/lang/String;
+	public static final field META_START_PROPERTY Ljava/lang/String;
+	public static final field META_TYPE_PROPERTY Ljava/lang/String;
+	public static final field TAGLESS_ENVELOPE_HEADER Ljava/lang/String;
+	public static final field TAGLESS_ENVELOPE_TYPE Ljava/lang/String;
+	public static final field code I
+	public fun <init> (Lhep/dataforge/io/IOPlugin;Lhep/dataforge/meta/Meta;)V
+	public synthetic fun <init> (Lhep/dataforge/io/IOPlugin;Lhep/dataforge/meta/Meta;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
+	public fun getDefaultMetaFormat ()Lhep/dataforge/io/MetaFormatFactory;
+	public final fun getIo ()Lhep/dataforge/io/IOPlugin;
+	public final fun getMeta ()Lhep/dataforge/meta/Meta;
+	public fun readObject (Lkotlinx/io/Input;)Lhep/dataforge/io/Envelope;
+	public synthetic fun readObject (Lkotlinx/io/Input;)Ljava/lang/Object;
+	public fun readPartial (Lkotlinx/io/Input;)Lhep/dataforge/io/PartialEnvelope;
+	public fun toMeta ()Lhep/dataforge/meta/Meta;
+	public fun writeEnvelope (Lkotlinx/io/Output;Lhep/dataforge/io/Envelope;Lhep/dataforge/io/MetaFormatFactory;Lhep/dataforge/meta/Meta;)V
+	public fun writeObject (Lkotlinx/io/Output;Lhep/dataforge/io/Envelope;)V
+	public synthetic fun writeObject (Lkotlinx/io/Output;Ljava/lang/Object;)V
+}
+
+public final class hep/dataforge/io/TaglessEnvelopeFormat$Companion : hep/dataforge/io/EnvelopeFormatFactory {
+	public fun getDefaultMetaFormat ()Lhep/dataforge/io/MetaFormatFactory;
+	public fun getName ()Lhep/dataforge/names/Name;
+	public fun getType ()Lkotlin/reflect/KClass;
+	public fun invoke (Lhep/dataforge/meta/Meta;Lhep/dataforge/context/Context;)Lhep/dataforge/io/EnvelopeFormat;
+	public synthetic fun invoke (Lhep/dataforge/meta/Meta;Lhep/dataforge/context/Context;)Ljava/lang/Object;
+	public fun peekFormat (Lhep/dataforge/io/IOPlugin;Lkotlinx/io/Input;)Lhep/dataforge/io/EnvelopeFormat;
+	public fun readObject (Lkotlinx/io/Input;)Lhep/dataforge/io/Envelope;
+	public synthetic fun readObject (Lkotlinx/io/Input;)Ljava/lang/Object;
+	public fun readPartial (Lkotlinx/io/Input;)Lhep/dataforge/io/PartialEnvelope;
+	public fun toMeta ()Lhep/dataforge/meta/Meta;
+	public fun writeEnvelope (Lkotlinx/io/Output;Lhep/dataforge/io/Envelope;Lhep/dataforge/io/MetaFormatFactory;Lhep/dataforge/meta/Meta;)V
+	public fun writeObject (Lkotlinx/io/Output;Lhep/dataforge/io/Envelope;)V
+	public synthetic fun writeObject (Lkotlinx/io/Output;Ljava/lang/Object;)V
+}
+
+public final class hep/dataforge/io/ValueIOFormat : hep/dataforge/io/IOFormat, hep/dataforge/io/IOFormatFactory {
+	public static final field INSTANCE Lhep/dataforge/io/ValueIOFormat;
+	public fun getName ()Lhep/dataforge/names/Name;
+	public fun getType ()Lkotlin/reflect/KClass;
+	public fun invoke (Lhep/dataforge/meta/Meta;Lhep/dataforge/context/Context;)Lhep/dataforge/io/IOFormat;
+	public synthetic fun invoke (Lhep/dataforge/meta/Meta;Lhep/dataforge/context/Context;)Ljava/lang/Object;
+	public fun readObject (Lkotlinx/io/Input;)Lhep/dataforge/values/Value;
+	public synthetic fun readObject (Lkotlinx/io/Input;)Ljava/lang/Object;
+	public fun toMeta ()Lhep/dataforge/meta/Meta;
+	public fun writeObject (Lkotlinx/io/Output;Lhep/dataforge/values/Value;)V
+	public synthetic fun writeObject (Lkotlinx/io/Output;Ljava/lang/Object;)V
+}
+
diff --git a/dataforge-io/build.gradle.kts b/dataforge-io/build.gradle.kts
index 15439cd4..d2e3a41a 100644
--- a/dataforge-io/build.gradle.kts
+++ b/dataforge-io/build.gradle.kts
@@ -1,17 +1,17 @@
-import scientifik.DependencySourceSet.TEST
-import scientifik.useSerialization
-
 plugins {
-    id("scientifik.mpp")
+    id("ru.mipt.npm.mpp")
+    id("ru.mipt.npm.native")
 }
 
 description = "IO module"
 
-useSerialization(sourceSet = TEST){
-    cbor()
+kscience {
+    useSerialization(sourceSet = ru.mipt.npm.gradle.DependencySourceSet.TEST) {
+        cbor()
+    }
 }
 
-val ioVersion by rootProject.extra("0.2.0-npm-dev-7")
+val ioVersion by rootProject.extra("0.2.0-npm-dev-11")
 
 kotlin {
     sourceSets {
diff --git a/dataforge-io/dataforge-io-yaml/api/dataforge-io-yaml.api b/dataforge-io/dataforge-io-yaml/api/dataforge-io-yaml.api
new file mode 100644
index 00000000..de7b3ab2
--- /dev/null
+++ b/dataforge-io/dataforge-io-yaml/api/dataforge-io-yaml.api
@@ -0,0 +1,59 @@
+public final class hep/dataforge/io/yaml/FrontMatterEnvelopeFormat : hep/dataforge/io/EnvelopeFormat {
+	public static final field Companion Lhep/dataforge/io/yaml/FrontMatterEnvelopeFormat$Companion;
+	public static final field SEPARATOR Ljava/lang/String;
+	public fun <init> (Lhep/dataforge/io/IOPlugin;Lhep/dataforge/meta/Meta;)V
+	public synthetic fun <init> (Lhep/dataforge/io/IOPlugin;Lhep/dataforge/meta/Meta;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
+	public fun getDefaultMetaFormat ()Lhep/dataforge/io/MetaFormatFactory;
+	public fun readObject (Lkotlinx/io/Input;)Lhep/dataforge/io/Envelope;
+	public synthetic fun readObject (Lkotlinx/io/Input;)Ljava/lang/Object;
+	public fun readPartial (Lkotlinx/io/Input;)Lhep/dataforge/io/PartialEnvelope;
+	public fun toMeta ()Lhep/dataforge/meta/Meta;
+	public fun writeEnvelope (Lkotlinx/io/Output;Lhep/dataforge/io/Envelope;Lhep/dataforge/io/MetaFormatFactory;Lhep/dataforge/meta/Meta;)V
+	public fun writeObject (Lkotlinx/io/Output;Lhep/dataforge/io/Envelope;)V
+	public synthetic fun writeObject (Lkotlinx/io/Output;Ljava/lang/Object;)V
+}
+
+public final class hep/dataforge/io/yaml/FrontMatterEnvelopeFormat$Companion : hep/dataforge/io/EnvelopeFormatFactory {
+	public fun getDefaultMetaFormat ()Lhep/dataforge/io/MetaFormatFactory;
+	public fun getName ()Lhep/dataforge/names/Name;
+	public fun getType ()Lkotlin/reflect/KClass;
+	public fun invoke (Lhep/dataforge/meta/Meta;Lhep/dataforge/context/Context;)Lhep/dataforge/io/EnvelopeFormat;
+	public synthetic fun invoke (Lhep/dataforge/meta/Meta;Lhep/dataforge/context/Context;)Ljava/lang/Object;
+	public fun peekFormat (Lhep/dataforge/io/IOPlugin;Lkotlinx/io/Input;)Lhep/dataforge/io/EnvelopeFormat;
+	public fun readObject (Lkotlinx/io/Input;)Lhep/dataforge/io/Envelope;
+	public synthetic fun readObject (Lkotlinx/io/Input;)Ljava/lang/Object;
+	public fun readPartial (Lkotlinx/io/Input;)Lhep/dataforge/io/PartialEnvelope;
+	public fun toMeta ()Lhep/dataforge/meta/Meta;
+	public fun writeEnvelope (Lkotlinx/io/Output;Lhep/dataforge/io/Envelope;Lhep/dataforge/io/MetaFormatFactory;Lhep/dataforge/meta/Meta;)V
+	public fun writeObject (Lkotlinx/io/Output;Lhep/dataforge/io/Envelope;)V
+	public synthetic fun writeObject (Lkotlinx/io/Output;Ljava/lang/Object;)V
+}
+
+public final class hep/dataforge/io/yaml/YamlMetaFormat : hep/dataforge/io/MetaFormat {
+	public static final field Companion Lhep/dataforge/io/yaml/YamlMetaFormat$Companion;
+	public fun <init> (Lhep/dataforge/meta/Meta;)V
+	public fun readMeta (Lkotlinx/io/Input;Lhep/dataforge/meta/descriptors/NodeDescriptor;)Lhep/dataforge/meta/Meta;
+	public fun readObject (Lkotlinx/io/Input;)Lhep/dataforge/meta/Meta;
+	public synthetic fun readObject (Lkotlinx/io/Input;)Ljava/lang/Object;
+	public fun toMeta ()Lhep/dataforge/meta/Meta;
+	public fun writeMeta (Lkotlinx/io/Output;Lhep/dataforge/meta/Meta;Lhep/dataforge/meta/descriptors/NodeDescriptor;)V
+	public fun writeObject (Lkotlinx/io/Output;Lhep/dataforge/meta/Meta;)V
+	public synthetic fun writeObject (Lkotlinx/io/Output;Ljava/lang/Object;)V
+}
+
+public final class hep/dataforge/io/yaml/YamlMetaFormat$Companion : hep/dataforge/io/MetaFormatFactory {
+	public fun getKey ()S
+	public fun getName ()Lhep/dataforge/names/Name;
+	public fun getShortName ()Ljava/lang/String;
+	public fun getType ()Lkotlin/reflect/KClass;
+	public fun invoke (Lhep/dataforge/meta/Meta;Lhep/dataforge/context/Context;)Lhep/dataforge/io/MetaFormat;
+	public synthetic fun invoke (Lhep/dataforge/meta/Meta;Lhep/dataforge/context/Context;)Ljava/lang/Object;
+	public fun readMeta (Lkotlinx/io/Input;Lhep/dataforge/meta/descriptors/NodeDescriptor;)Lhep/dataforge/meta/Meta;
+	public fun readObject (Lkotlinx/io/Input;)Lhep/dataforge/meta/Meta;
+	public synthetic fun readObject (Lkotlinx/io/Input;)Ljava/lang/Object;
+	public fun toMeta ()Lhep/dataforge/meta/Meta;
+	public fun writeMeta (Lkotlinx/io/Output;Lhep/dataforge/meta/Meta;Lhep/dataforge/meta/descriptors/NodeDescriptor;)V
+	public fun writeObject (Lkotlinx/io/Output;Lhep/dataforge/meta/Meta;)V
+	public synthetic fun writeObject (Lkotlinx/io/Output;Ljava/lang/Object;)V
+}
+
diff --git a/dataforge-io/dataforge-io-yaml/build.gradle.kts b/dataforge-io/dataforge-io-yaml/build.gradle.kts
index f29bff4a..720e1fba 100644
--- a/dataforge-io/dataforge-io-yaml/build.gradle.kts
+++ b/dataforge-io/dataforge-io-yaml/build.gradle.kts
@@ -1,13 +1,13 @@
-import scientifik.useSerialization
-
 plugins {
-    id("scientifik.jvm")
+    id("ru.mipt.npm.jvm")
 }
 
 description = "YAML meta IO"
 
-useSerialization{
-    yaml()
+kscience {
+    useSerialization {
+        yaml()
+    }
 }
 
 dependencies {
diff --git a/dataforge-io/dataforge-io-yaml/src/main/kotlin/hep/dataforge/io/yaml/FrontMatterEnvelopeFormat.kt b/dataforge-io/dataforge-io-yaml/src/main/kotlin/hep/dataforge/io/yaml/FrontMatterEnvelopeFormat.kt
index 0fffdb7e..aa2537be 100644
--- a/dataforge-io/dataforge-io-yaml/src/main/kotlin/hep/dataforge/io/yaml/FrontMatterEnvelopeFormat.kt
+++ b/dataforge-io/dataforge-io-yaml/src/main/kotlin/hep/dataforge/io/yaml/FrontMatterEnvelopeFormat.kt
@@ -9,20 +9,19 @@ import hep.dataforge.meta.Meta
 import kotlinx.io.*
 import kotlinx.io.text.readUtf8Line
 import kotlinx.io.text.writeUtf8String
-import kotlinx.serialization.toUtf8Bytes
 
 @DFExperimental
-class FrontMatterEnvelopeFormat(
-    val io: IOPlugin,
-    val meta: Meta = Meta.EMPTY
+public class FrontMatterEnvelopeFormat(
+    private val io: IOPlugin,
+    private val meta: Meta = Meta.EMPTY,
 ) : EnvelopeFormat {
 
-    override fun Input.readPartial(): PartialEnvelope {
-        var line: String = ""
+    override fun readPartial(input: Input): PartialEnvelope {
+        var line = ""
         var offset = 0u
         do {
-            line = readUtf8Line() //?: error("Input does not contain front matter separator")
-            offset += line.toUtf8Bytes().size.toUInt()
+            line = input.readUtf8Line() //?: error("Input does not contain front matter separator")
+            offset += line.toByteArray().size.toUInt()
         } while (!line.startsWith(SEPARATOR))
 
         val readMetaFormat =
@@ -32,22 +31,21 @@ class FrontMatterEnvelopeFormat(
         //TODO replace by preview
         val meta = Binary {
             do {
-                line = readUtf8Line()
+                line = input.readUtf8Line()
                 writeUtf8String(line + "\r\n")
-                offset += line.toUtf8Bytes().size.toUInt()
+                offset += line.toByteArray().size.toUInt()
             } while (!line.startsWith(SEPARATOR))
         }.read {
-            readMetaFormat.run {
-                readMeta()
-            }
+            readMetaFormat.readMeta(input)
+
         }
         return PartialEnvelope(meta, offset, null)
     }
 
-    override fun Input.readObject(): Envelope {
-        var line: String = ""
+    override fun readObject(input: Input): Envelope {
+        var line = ""
         do {
-            line = readUtf8Line() //?: error("Input does not contain front matter separator")
+            line = input.readUtf8Line() //?: error("Input does not contain front matter separator")
         } while (!line.startsWith(SEPARATOR))
 
         val readMetaFormat =
@@ -56,26 +54,29 @@ class FrontMatterEnvelopeFormat(
 
         val meta = Binary {
             do {
-                writeUtf8String(readUtf8Line() + "\r\n")
+                writeUtf8String(input.readUtf8Line() + "\r\n")
             } while (!line.startsWith(SEPARATOR))
         }.read {
-            readMetaFormat.run {
-                readMeta()
-            }
+            readMetaFormat.readMeta(input)
         }
-        val bytes = readByteArray()
+        val bytes = input.readByteArray()
         val data = bytes.asBinary()
         return SimpleEnvelope(meta, data)
     }
 
-    override fun Output.writeEnvelope(envelope: Envelope, metaFormatFactory: MetaFormatFactory, formatMeta: Meta) {
-        val metaFormat = metaFormatFactory(formatMeta, io.context)
-        writeRawString("$SEPARATOR\r\n")
-        metaFormat.run { writeObject(envelope.meta) }
-        writeRawString("$SEPARATOR\r\n")
+    override fun writeEnvelope(
+        output: Output,
+        envelope: Envelope,
+        metaFormatFactory: MetaFormatFactory,
+        formatMeta: Meta,
+    ) {
+        val metaFormat = metaFormatFactory(formatMeta, this@FrontMatterEnvelopeFormat.io.context)
+        output.writeRawString("${hep.dataforge.io.yaml.FrontMatterEnvelopeFormat.Companion.SEPARATOR}\r\n")
+        metaFormat.run { this.writeObject(output, envelope.meta) }
+        output.writeRawString("${hep.dataforge.io.yaml.FrontMatterEnvelopeFormat.Companion.SEPARATOR}\r\n")
         //Printing data
         envelope.data?.let { data ->
-            writeBinary(data)
+            output.writeBinary(data)
         }
     }
 
@@ -84,8 +85,8 @@ class FrontMatterEnvelopeFormat(
         META_KEY put meta
     }
 
-    companion object : EnvelopeFormatFactory {
-        const val SEPARATOR = "---"
+    public companion object : EnvelopeFormatFactory {
+        public const val SEPARATOR = "---"
 
         private val metaTypeRegex = "---(\\w*)\\s*".toRegex()
 
@@ -106,14 +107,18 @@ class FrontMatterEnvelopeFormat(
 
         private val default by lazy { invoke() }
 
-        override fun Input.readPartial(): PartialEnvelope =
-            default.run { readPartial() }
+        override fun readPartial(input: Input): PartialEnvelope =
+            default.readPartial(input)
 
-        override fun Output.writeEnvelope(envelope: Envelope, metaFormatFactory: MetaFormatFactory, formatMeta: Meta) =
-            default.run { writeEnvelope(envelope, metaFormatFactory, formatMeta) }
+        override fun writeEnvelope(
+            output: Output,
+            envelope: Envelope,
+            metaFormatFactory: MetaFormatFactory,
+            formatMeta: Meta,
+        ): Unit = default.writeEnvelope(output, envelope, metaFormatFactory, formatMeta)
 
-        override fun Input.readObject(): Envelope =
-            default.run { readObject() }
+
+        override fun readObject(input: Input): Envelope = default.readObject(input)
 
     }
 }
\ No newline at end of file
diff --git a/dataforge-io/dataforge-io-yaml/src/main/kotlin/hep/dataforge/io/yaml/YamlMetaFormat.kt b/dataforge-io/dataforge-io-yaml/src/main/kotlin/hep/dataforge/io/yaml/YamlMetaFormat.kt
index 5806abf8..18e8af06 100644
--- a/dataforge-io/dataforge-io-yaml/src/main/kotlin/hep/dataforge/io/yaml/YamlMetaFormat.kt
+++ b/dataforge-io/dataforge-io-yaml/src/main/kotlin/hep/dataforge/io/yaml/YamlMetaFormat.kt
@@ -16,17 +16,20 @@ import kotlinx.io.asInputStream
 import kotlinx.io.text.writeUtf8String
 import org.yaml.snakeyaml.Yaml
 
+/**
+ * Represent meta as Yaml
+ */
 @DFExperimental
-class YamlMetaFormat(val meta: Meta) : MetaFormat {
+public class YamlMetaFormat(private val meta: Meta) : MetaFormat {
     private val yaml = Yaml()
 
-    override fun Output.writeMeta(meta: Meta, descriptor: NodeDescriptor?) {
+    override fun writeMeta(output: Output, meta: Meta, descriptor: NodeDescriptor?) {
         val string = yaml.dump(meta.toMap(descriptor))
-        writeUtf8String(string)
+        output.writeUtf8String(string)
     }
 
-    override fun Input.readMeta(descriptor: NodeDescriptor?): Meta {
-        val map: Map<String, Any?> = yaml.load(asInputStream())
+    override fun readMeta(input: Input, descriptor: NodeDescriptor?): Meta {
+        val map: Map<String, Any?> = yaml.load(input.asInputStream())
         return map.toMeta(descriptor)
     }
 
@@ -35,19 +38,19 @@ class YamlMetaFormat(val meta: Meta) : MetaFormat {
         META_KEY put meta
     }
 
-    companion object : MetaFormatFactory {
+    public companion object : MetaFormatFactory {
         override fun invoke(meta: Meta, context: Context): MetaFormat = YamlMetaFormat(meta)
 
-        override val shortName = "yaml"
+        override val shortName: String = "yaml"
 
         override val key: Short = 0x594d //YM
 
         private val default = YamlMetaFormat()
 
-        override fun Output.writeMeta(meta: Meta, descriptor: NodeDescriptor?) =
-            default.run { writeMeta(meta, descriptor) }
+        override fun writeMeta(output: Output, meta: Meta, descriptor: NodeDescriptor?): Unit =
+            default.writeMeta(output, meta, descriptor)
 
-        override fun Input.readMeta(descriptor: NodeDescriptor?): Meta =
-            default.run { readMeta(descriptor) }
+        override fun readMeta(input: kotlinx.io.Input, descriptor: NodeDescriptor?): Meta =
+            default.readMeta(input, descriptor)
     }
 }
\ No newline at end of file
diff --git a/dataforge-io/src/commonMain/kotlin/hep/dataforge/io/BinaryMetaFormat.kt b/dataforge-io/src/commonMain/kotlin/hep/dataforge/io/BinaryMetaFormat.kt
index e753b56c..547d567c 100644
--- a/dataforge-io/src/commonMain/kotlin/hep/dataforge/io/BinaryMetaFormat.kt
+++ b/dataforge-io/src/commonMain/kotlin/hep/dataforge/io/BinaryMetaFormat.kt
@@ -11,14 +11,18 @@ import kotlinx.io.*
 import kotlinx.io.text.readUtf8String
 import kotlinx.io.text.writeUtf8String
 
-object BinaryMetaFormat : MetaFormat, MetaFormatFactory {
+/**
+ * A DataForge-specific simplified binary format for meta
+ * TODO add description
+ */
+public object BinaryMetaFormat : MetaFormat, MetaFormatFactory {
     override val shortName: String = "bin"
     override val key: Short = 0x4249//BI
 
     override fun invoke(meta: Meta, context: Context): MetaFormat = this
 
-    override fun Input.readMeta(descriptor: NodeDescriptor?): Meta {
-        return (readMetaItem() as MetaItem.NodeItem).node
+    override fun readMeta(input: Input, descriptor: NodeDescriptor?): Meta {
+        return (input.readMetaItem() as MetaItem.NodeItem).node
     }
 
     private fun Output.writeChar(char: Char) = writeByte(char.toByte())
@@ -28,7 +32,7 @@ object BinaryMetaFormat : MetaFormat, MetaFormatFactory {
         writeUtf8String(str)
     }
 
-    fun Output.writeValue(value: Value) {
+    public fun Output.writeValue(value: Value) {
         if (value.isList()) {
             writeChar('L')
             writeInt(value.list.size)
@@ -75,17 +79,21 @@ object BinaryMetaFormat : MetaFormat, MetaFormatFactory {
         }
     }
 
-    override fun Output.writeMeta(meta: Meta, descriptor: NodeDescriptor?) {
-        writeChar('M')
-        writeInt(meta.items.size)
+    override fun writeMeta(
+        output: kotlinx.io.Output,
+        meta: hep.dataforge.meta.Meta,
+        descriptor: hep.dataforge.meta.descriptors.NodeDescriptor?
+    ) {
+        output.writeChar('M')
+        output.writeInt(meta.items.size)
         meta.items.forEach { (key, item) ->
-            writeString(key.toString())
+            output.writeString(key.toString())
             when (item) {
                 is MetaItem.ValueItem -> {
-                    writeValue(item.value)
+                    output.writeValue(item.value)
                 }
                 is MetaItem.NodeItem -> {
-                    writeObject(item.node)
+                    writeObject(output, item.node)
                 }
             }
         }
@@ -97,7 +105,7 @@ object BinaryMetaFormat : MetaFormat, MetaFormatFactory {
     }
 
     @Suppress("UNCHECKED_CAST")
-    fun Input.readMetaItem(): MetaItem<MetaBuilder> {
+    public fun Input.readMetaItem(): MetaItem<MetaBuilder> {
         return when (val keyChar = readByte().toChar()) {
             'S' -> MetaItem.ValueItem(StringValue(readString()))
             'N' -> MetaItem.ValueItem(Null)
diff --git a/dataforge-io/src/commonMain/kotlin/hep/dataforge/io/Consumer.kt b/dataforge-io/src/commonMain/kotlin/hep/dataforge/io/Consumer.kt
new file mode 100644
index 00000000..0ef5d327
--- /dev/null
+++ b/dataforge-io/src/commonMain/kotlin/hep/dataforge/io/Consumer.kt
@@ -0,0 +1,11 @@
+package hep.dataforge.io
+
+import hep.dataforge.meta.DFExperimental
+
+/**
+ * A fire-and-forget consumer of messages
+ */
+@DFExperimental
+public interface Consumer {
+    public fun consume(message: Envelope): Unit
+}
\ No newline at end of file
diff --git a/dataforge-io/src/commonMain/kotlin/hep/dataforge/io/Envelope.kt b/dataforge-io/src/commonMain/kotlin/hep/dataforge/io/Envelope.kt
index d7c60116..992a080f 100644
--- a/dataforge-io/src/commonMain/kotlin/hep/dataforge/io/Envelope.kt
+++ b/dataforge-io/src/commonMain/kotlin/hep/dataforge/io/Envelope.kt
@@ -4,64 +4,66 @@ import hep.dataforge.meta.Laminate
 import hep.dataforge.meta.Meta
 import hep.dataforge.meta.get
 import hep.dataforge.meta.string
+import hep.dataforge.names.Name
 import hep.dataforge.names.asName
 import hep.dataforge.names.plus
 import kotlinx.io.Binary
 
-interface Envelope {
-    val meta: Meta
-    val data: Binary?
+public interface Envelope {
+    public val meta: Meta
+    public val data: Binary?
 
-    companion object {
+    public companion object {
 
         /**
          * meta keys
          */
-        val ENVELOPE_NODE_KEY = "@envelope".asName()
-        val ENVELOPE_TYPE_KEY = ENVELOPE_NODE_KEY + "type"
-        val ENVELOPE_DATA_TYPE_KEY = ENVELOPE_NODE_KEY + "dataType"
-        val ENVELOPE_DATA_ID_KEY = ENVELOPE_NODE_KEY + "dataID"
-        val ENVELOPE_DESCRIPTION_KEY = ENVELOPE_NODE_KEY + "description"
-        val ENVELOPE_NAME_KEY = ENVELOPE_NODE_KEY + "name"
+        public val ENVELOPE_NODE_KEY: Name = "@envelope".asName()
+        public val ENVELOPE_TYPE_KEY: Name = ENVELOPE_NODE_KEY + "type"
+        public val ENVELOPE_DATA_TYPE_KEY: Name = ENVELOPE_NODE_KEY + "dataType"
+        public val ENVELOPE_DATA_ID_KEY: Name = ENVELOPE_NODE_KEY + "dataID"
+        public val ENVELOPE_DESCRIPTION_KEY: Name = ENVELOPE_NODE_KEY + "description"
+        public val ENVELOPE_NAME_KEY: Name = ENVELOPE_NODE_KEY + "name"
         //const val ENVELOPE_TIME_KEY = "@envelope.time"
 
         /**
          * Build a static envelope using provided builder
          */
-        inline operator fun invoke(block: EnvelopeBuilder.() -> Unit) = EnvelopeBuilder().apply(block).build()
+        public inline operator fun invoke(block: EnvelopeBuilder.() -> Unit): Envelope =
+            EnvelopeBuilder().apply(block).seal()
     }
 }
 
-class SimpleEnvelope(override val meta: Meta, override val data: Binary?) : Envelope
+public class SimpleEnvelope(override val meta: Meta, override val data: Binary?) : Envelope
 
 /**
  * The purpose of the envelope
  *
  */
-val Envelope.type: String? get() = meta[Envelope.ENVELOPE_TYPE_KEY].string
+public val Envelope.type: String? get() = meta[Envelope.ENVELOPE_TYPE_KEY].string
 
 /**
  * The type of data encoding
  *
  */
-val Envelope.dataType: String? get() = meta[Envelope.ENVELOPE_DATA_TYPE_KEY].string
+public val Envelope.dataType: String? get() = meta[Envelope.ENVELOPE_DATA_TYPE_KEY].string
 
 /**
  * Textual user friendly description
  *
  */
-val Envelope.description: String? get() = meta[Envelope.ENVELOPE_DESCRIPTION_KEY].string
+public val Envelope.description: String? get() = meta[Envelope.ENVELOPE_DESCRIPTION_KEY].string
 
 /**
  * An optional unique identifier that is used for data comparison. Data without identifier could not be compared to another data.
  */
-val Envelope.dataID: String? get() = meta[Envelope.ENVELOPE_DATA_ID_KEY].string
+public val Envelope.dataID: String? get() = meta[Envelope.ENVELOPE_DATA_ID_KEY].string
 
-fun Envelope.metaEquals(other: Envelope): Boolean = this.meta == other.meta
+public fun Envelope.metaEquals(other: Envelope): Boolean = this.meta == other.meta
 
-fun Envelope.dataEquals(other: Envelope): Boolean = this.dataID != null && this.dataID == other.dataID
+public fun Envelope.dataEquals(other: Envelope): Boolean = this.dataID != null && this.dataID == other.dataID
 
-fun Envelope.contentEquals(other: Envelope): Boolean {
+public fun Envelope.contentEquals(other: Envelope): Boolean {
     return (this === other || (metaEquals(other) && dataEquals(other)))
 }
 
@@ -69,7 +71,7 @@ fun Envelope.contentEquals(other: Envelope): Boolean {
 /**
  * An envelope, which wraps existing envelope and adds one or several additional layers of meta
  */
-class ProxyEnvelope(val source: Envelope, vararg meta: Meta) : Envelope {
+public class ProxyEnvelope(public val source: Envelope, vararg meta: Meta) : Envelope {
     override val meta: Laminate = Laminate(*meta, source.meta)
     override val data: Binary? get() = source.data
 }
@@ -77,7 +79,7 @@ class ProxyEnvelope(val source: Envelope, vararg meta: Meta) : Envelope {
 /**
  * Add few meta layers to existing envelope (on top of existing meta)
  */
-fun Envelope.withMetaLayers(vararg layers: Meta): Envelope {
+public fun Envelope.withMetaLayers(vararg layers: Meta): Envelope {
     return when {
         layers.isEmpty() -> this
         this is ProxyEnvelope -> ProxyEnvelope(source, *layers, *this.meta.layers.toTypedArray())
diff --git a/dataforge-io/src/commonMain/kotlin/hep/dataforge/io/EnvelopeBuilder.kt b/dataforge-io/src/commonMain/kotlin/hep/dataforge/io/EnvelopeBuilder.kt
index c37f7c38..73775af3 100644
--- a/dataforge-io/src/commonMain/kotlin/hep/dataforge/io/EnvelopeBuilder.kt
+++ b/dataforge-io/src/commonMain/kotlin/hep/dataforge/io/EnvelopeBuilder.kt
@@ -3,42 +3,44 @@ package hep.dataforge.io
 import hep.dataforge.meta.*
 import kotlinx.io.*
 
-class EnvelopeBuilder {
+public class EnvelopeBuilder : Envelope {
     private val metaBuilder = MetaBuilder()
-    var data: Binary? = null
 
-    fun meta(block: MetaBuilder.() -> Unit) {
+    override var data: Binary? = null
+    override var meta: Meta
+        get() = metaBuilder
+        set(value) {
+            metaBuilder.update(value)
+        }
+
+    public fun meta(block: MetaBuilder.() -> Unit) {
         metaBuilder.apply(block)
     }
 
-    fun meta(meta: Meta) {
-        metaBuilder.update(meta)
-    }
-
     /**
      * The general purpose of the envelope
      */
-    var type by metaBuilder.string(key = Envelope.ENVELOPE_TYPE_KEY)
-    var dataType by metaBuilder.string(key = Envelope.ENVELOPE_DATA_TYPE_KEY)
+    public var type: String? by metaBuilder.string(key = Envelope.ENVELOPE_TYPE_KEY)
+    public var dataType: String? by metaBuilder.string(key = Envelope.ENVELOPE_DATA_TYPE_KEY)
 
     /**
      * Data unique identifier to bypass identity checks
      */
-    var dataID by metaBuilder.string(key = Envelope.ENVELOPE_DATA_ID_KEY)
-    var description by metaBuilder.string(key = Envelope.ENVELOPE_DESCRIPTION_KEY)
-    var name by metaBuilder.string(key = Envelope.ENVELOPE_NAME_KEY)
+    public var dataID: String? by metaBuilder.string(key = Envelope.ENVELOPE_DATA_ID_KEY)
+    public var description: String? by metaBuilder.string(key = Envelope.ENVELOPE_DESCRIPTION_KEY)
+    public var name: String? by metaBuilder.string(key = Envelope.ENVELOPE_NAME_KEY)
 
     /**
      * Construct a data binary from given builder
      */
     @OptIn(ExperimentalIoApi::class)
-    fun data(block: Output.() -> Unit) {
+    public fun data(block: Output.() -> Unit) {
         val arrayBuilder = ByteArrayOutput()
         arrayBuilder.block()
         data = arrayBuilder.toByteArray().asBinary()
     }
 
-    fun build() = SimpleEnvelope(metaBuilder.seal(), data)
+    public fun seal(): Envelope = SimpleEnvelope(metaBuilder.seal(), data)
 
 }
 
diff --git a/dataforge-io/src/commonMain/kotlin/hep/dataforge/io/EnvelopeFormat.kt b/dataforge-io/src/commonMain/kotlin/hep/dataforge/io/EnvelopeFormat.kt
index 9b819a97..b02052c1 100644
--- a/dataforge-io/src/commonMain/kotlin/hep/dataforge/io/EnvelopeFormat.kt
+++ b/dataforge-io/src/commonMain/kotlin/hep/dataforge/io/EnvelopeFormat.kt
@@ -13,31 +13,29 @@ import kotlin.reflect.KClass
 /**
  * A partially read envelope with meta, but without data
  */
-@ExperimentalUnsignedTypes
-data class PartialEnvelope(val meta: Meta, val dataOffset: UInt, val dataSize: ULong?)
+public data class PartialEnvelope(val meta: Meta, val dataOffset: UInt, val dataSize: ULong?)
 
-interface EnvelopeFormat : IOFormat<Envelope> {
-    val defaultMetaFormat: MetaFormatFactory get() = JsonMetaFormat
+public interface EnvelopeFormat : IOFormat<Envelope> {
+    public val defaultMetaFormat: MetaFormatFactory get() = JsonMetaFormat
 
-    fun Input.readPartial(): PartialEnvelope
+    public fun readPartial(input: Input): PartialEnvelope
 
-    fun Output.writeEnvelope(
+    public fun writeEnvelope(
+        output: Output,
         envelope: Envelope,
         metaFormatFactory: MetaFormatFactory = defaultMetaFormat,
-        formatMeta: Meta = Meta.EMPTY
+        formatMeta: Meta = Meta.EMPTY,
     )
 
-    override fun Input.readObject(): Envelope
+    override fun readObject(input: Input): Envelope
 
-    override fun Output.writeObject(obj: Envelope): Unit = writeEnvelope(obj)
+    override fun writeObject(output: Output, obj: Envelope): Unit = writeEnvelope(output, obj)
 }
 
-fun EnvelopeFormat.readPartial(input: Input) = input.readPartial()
-
-fun EnvelopeFormat.read(input: Input) = input.readObject()
+public fun EnvelopeFormat.read(input: Input): Envelope = readObject(input)
 
 @Type(ENVELOPE_FORMAT_TYPE)
-interface EnvelopeFormatFactory : IOFormatFactory<Envelope>, EnvelopeFormat {
+public interface EnvelopeFormatFactory : IOFormatFactory<Envelope>, EnvelopeFormat {
     override val name: Name get() = "envelope".asName()
     override val type: KClass<out Envelope> get() = Envelope::class
 
@@ -47,9 +45,9 @@ interface EnvelopeFormatFactory : IOFormatFactory<Envelope>, EnvelopeFormat {
      * Try to infer specific format from input and return null if the attempt is failed.
      * This method does **not** return Input into initial state.
      */
-    fun peekFormat(io: IOPlugin, input: Input): EnvelopeFormat?
+    public fun peekFormat(io: IOPlugin, input: Input): EnvelopeFormat?
 
-    companion object {
-        const val ENVELOPE_FORMAT_TYPE = "io.format.envelope"
+    public companion object {
+        public const val ENVELOPE_FORMAT_TYPE: String = "io.format.envelope"
     }
 }
\ No newline at end of file
diff --git a/dataforge-io/src/commonMain/kotlin/hep/dataforge/io/EnvelopeParts.kt b/dataforge-io/src/commonMain/kotlin/hep/dataforge/io/EnvelopeParts.kt
index 19ccb458..cae87229 100644
--- a/dataforge-io/src/commonMain/kotlin/hep/dataforge/io/EnvelopeParts.kt
+++ b/dataforge-io/src/commonMain/kotlin/hep/dataforge/io/EnvelopeParts.kt
@@ -31,11 +31,11 @@ private class PartDescriptor : Scheme() {
     }
 }
 
-data class EnvelopePart(val binary: Binary, val description: Meta?)
+public data class EnvelopePart(val binary: Binary, val description: Meta?)
 
-typealias EnvelopeParts = List<EnvelopePart>
+public typealias EnvelopeParts = List<EnvelopePart>
 
-fun EnvelopeBuilder.multipart(
+public fun EnvelopeBuilder.multipart(
     parts: EnvelopeParts,
     separator: String = DEFAULT_MULTIPART_DATA_SEPARATOR
 ) {
@@ -69,7 +69,7 @@ fun EnvelopeBuilder.multipart(
     }
 }
 
-fun EnvelopeBuilder.envelopes(
+public fun EnvelopeBuilder.envelopes(
     envelopes: List<Envelope>,
     format: EnvelopeFormat = TaggedEnvelopeFormat,
     separator: String = DEFAULT_MULTIPART_DATA_SEPARATOR
@@ -84,11 +84,11 @@ fun EnvelopeBuilder.envelopes(
     multipart(parts, separator)
 }
 
-fun Envelope.parts(): EnvelopeParts {
+public fun Envelope.parts(): EnvelopeParts {
     if (data == null) return emptyList()
     //TODO add zip folder reader
     val parts = meta.getIndexed(PARTS_KEY).values.mapNotNull { it.node }.map {
-        PartDescriptor.wrap(it)
+        PartDescriptor.read(it)
     }
     return if (parts.isEmpty()) {
         listOf(EnvelopePart(data!!, meta[MULTIPART_KEY].node))
@@ -101,14 +101,14 @@ fun Envelope.parts(): EnvelopeParts {
     }
 }
 
-fun EnvelopePart.envelope(format: EnvelopeFormat): Envelope = binary.readWith(format)
+public fun EnvelopePart.envelope(format: EnvelopeFormat): Envelope = binary.readWith(format)
 
-val EnvelopePart.name: String? get() = description?.get("name").string
+public val EnvelopePart.name: String? get() = description?.get("name").string
 
 /**
  * Represent envelope part by an envelope
  */
-fun EnvelopePart.envelope(plugin: IOPlugin): Envelope {
+public fun EnvelopePart.envelope(plugin: IOPlugin): Envelope {
     val formatItem = description?.get(PART_FORMAT_KEY)
     return if (formatItem != null) {
         val format: EnvelopeFormat = plugin.resolveEnvelopeFormat(formatItem)
diff --git a/dataforge-io/src/commonMain/kotlin/hep/dataforge/io/IOFormat.kt b/dataforge-io/src/commonMain/kotlin/hep/dataforge/io/IOFormat.kt
index 7946c536..7fe4c970 100644
--- a/dataforge-io/src/commonMain/kotlin/hep/dataforge/io/IOFormat.kt
+++ b/dataforge-io/src/commonMain/kotlin/hep/dataforge/io/IOFormat.kt
@@ -20,41 +20,42 @@ import kotlin.reflect.KClass
 /**
  * And interface for reading and writing objects into with IO streams
  */
-interface IOFormat<T : Any> : MetaRepr {
-    fun Output.writeObject(obj: T)
-    fun Input.readObject(): T
+public interface IOFormat<T : Any> : MetaRepr {
+    public fun writeObject(output: Output, obj: T)
+    public fun readObject(input: Input): T
 
-    companion object{
-        val NAME_KEY = "name".asName()
-        val META_KEY = "meta".asName()
+    public companion object {
+        public val NAME_KEY: Name = "name".asName()
+        public val META_KEY: Name = "meta".asName()
     }
 }
 
-fun <T : Any> Input.readWith(format: IOFormat<T>): T = format.run { readObject() }
+public fun <T : Any> Input.readWith(format: IOFormat<T>): T = format.readObject(this@readWith)
 
 /**
  * Read given binary as object using given format
  */
-fun <T : Any> Binary.readWith(format: IOFormat<T>): T = read {
+public fun <T : Any> Binary.readWith(format: IOFormat<T>): T = read {
     readWith(format)
 }
 
-fun <T : Any> Output.writeWith(format: IOFormat<T>, obj: T) = format.run { writeObject(obj) }
+public fun <T : Any> Output.writeWith(format: IOFormat<T>, obj: T): Unit =
+    format.run { writeObject(this@writeWith, obj) }
 
-class ListIOFormat<T : Any>(val format: IOFormat<T>) : IOFormat<List<T>> {
-    override fun Output.writeObject(obj: List<T>) {
-        writeInt(obj.size)
-        format.run {
+public class ListIOFormat<T : Any>(public val format: IOFormat<T>) : IOFormat<List<T>> {
+    override fun writeObject(output: Output, obj: List<T>) {
+        output.writeInt(obj.size)
+        this.format.run {
             obj.forEach {
-                writeObject(it)
+                writeObject(output, it)
             }
         }
     }
 
-    override fun Input.readObject(): List<T> {
-        val size = readInt()
+    override fun readObject(input: Input): List<T> {
+        val size = input.readInt()
         return format.run {
-            List(size) { readObject() }
+            List(size) { readObject(input) }
         }
     }
 
@@ -64,9 +65,9 @@ class ListIOFormat<T : Any>(val format: IOFormat<T>) : IOFormat<List<T>> {
     }
 }
 
-val <T : Any> IOFormat<T>.list get() = ListIOFormat(this)
+//public val <T : Any> IOFormat<T>.list: ListIOFormat<T> get() = ListIOFormat(this)
 
-fun ObjectPool<Buffer>.fill(block: Buffer.() -> Unit): Buffer {
+public fun ObjectPool<Buffer>.fill(block: Buffer.() -> Unit): Buffer {
     val buffer = borrow()
     return try {
         buffer.apply(block)
@@ -77,50 +78,50 @@ fun ObjectPool<Buffer>.fill(block: Buffer.() -> Unit): Buffer {
 }
 
 @Type(IO_FORMAT_TYPE)
-interface IOFormatFactory<T : Any> : Factory<IOFormat<T>>, Named, MetaRepr {
+public interface IOFormatFactory<T : Any> : Factory<IOFormat<T>>, Named, MetaRepr {
     /**
      * Explicit type for dynamic type checks
      */
-    val type: KClass<out T>
+    public val type: KClass<out T>
 
     override fun toMeta(): Meta = Meta {
         NAME_KEY put name.toString()
     }
 
-    companion object {
-        const val IO_FORMAT_TYPE = "io.format"
+    public companion object {
+        public const val IO_FORMAT_TYPE: String = "io.format"
     }
 }
 
-fun <T : Any> IOFormat<T>.toBinary(obj: T): Binary = Binary { writeObject(obj) }
+public fun <T : Any> IOFormat<T>.toBinary(obj: T): Binary = Binary { writeObject(this, obj) }
 
-object DoubleIOFormat : IOFormat<Double>, IOFormatFactory<Double> {
+public object DoubleIOFormat : IOFormat<Double>, IOFormatFactory<Double> {
     override fun invoke(meta: Meta, context: Context): IOFormat<Double> = this
 
     override val name: Name = "double".asName()
 
     override val type: KClass<out Double> get() = Double::class
 
-    override fun Output.writeObject(obj: Double) {
-        writeDouble(obj)
+    override fun writeObject(output: Output, obj: kotlin.Double) {
+        output.writeDouble(obj)
     }
 
-    override fun Input.readObject(): Double = readDouble()
+    override fun readObject(input: Input): Double = input.readDouble()
 }
 
-object ValueIOFormat : IOFormat<Value>, IOFormatFactory<Value> {
+public object ValueIOFormat : IOFormat<Value>, IOFormatFactory<Value> {
     override fun invoke(meta: Meta, context: Context): IOFormat<Value> = this
 
     override val name: Name = "value".asName()
 
     override val type: KClass<out Value> get() = Value::class
 
-    override fun Output.writeObject(obj: Value) {
-        BinaryMetaFormat.run { writeValue(obj) }
+    override fun writeObject(output: Output, obj: Value) {
+        BinaryMetaFormat.run { output.writeValue(obj) }
     }
 
-    override fun Input.readObject(): Value {
-        return (BinaryMetaFormat.run { readMetaItem() } as? MetaItem.ValueItem)?.value
+    override fun readObject(input: Input): Value {
+        return (BinaryMetaFormat.run { input.readMetaItem() } as? MetaItem.ValueItem)?.value
             ?: error("The item is not a value")
     }
 }
\ No newline at end of file
diff --git a/dataforge-io/src/commonMain/kotlin/hep/dataforge/io/IOPlugin.kt b/dataforge-io/src/commonMain/kotlin/hep/dataforge/io/IOPlugin.kt
index 73fd26f1..f0c47609 100644
--- a/dataforge-io/src/commonMain/kotlin/hep/dataforge/io/IOPlugin.kt
+++ b/dataforge-io/src/commonMain/kotlin/hep/dataforge/io/IOPlugin.kt
@@ -11,14 +11,14 @@ import hep.dataforge.names.Name
 import hep.dataforge.names.toName
 import kotlin.reflect.KClass
 
-class IOPlugin(meta: Meta) : AbstractPlugin(meta) {
+public class IOPlugin(meta: Meta) : AbstractPlugin(meta) {
     override val tag: PluginTag get() = Companion.tag
 
-    val ioFormatFactories by lazy {
-        context.content<IOFormatFactory<*>>(IO_FORMAT_TYPE).values
+    public val ioFormatFactories: Collection<IOFormatFactory<*>> by lazy {
+        context.gather<IOFormatFactory<*>>(IO_FORMAT_TYPE).values
     }
 
-    fun <T : Any> resolveIOFormat(item: MetaItem<*>, type: KClass<out T>): IOFormat<T>? {
+    public fun <T : Any> resolveIOFormat(item: MetaItem<*>, type: KClass<out T>): IOFormat<T>? {
         val key = item.string ?: item.node[NAME_KEY]?.string ?: error("Format name not defined")
         val name = key.toName()
         return ioFormatFactories.find { it.name == name }?.let {
@@ -29,40 +29,40 @@ class IOPlugin(meta: Meta) : AbstractPlugin(meta) {
     }
 
 
-    val metaFormatFactories by lazy {
-        context.content<MetaFormatFactory>(META_FORMAT_TYPE).values
+    public val metaFormatFactories: Collection<MetaFormatFactory> by lazy {
+        context.gather<MetaFormatFactory>(META_FORMAT_TYPE).values
     }
 
-    fun resolveMetaFormat(key: Short, meta: Meta = Meta.EMPTY): MetaFormat? =
+    public fun resolveMetaFormat(key: Short, meta: Meta = Meta.EMPTY): MetaFormat? =
         metaFormatFactories.find { it.key == key }?.invoke(meta)
 
-    fun resolveMetaFormat(name: String, meta: Meta = Meta.EMPTY): MetaFormat? =
+    public fun resolveMetaFormat(name: String, meta: Meta = Meta.EMPTY): MetaFormat? =
         metaFormatFactories.find { it.shortName == name }?.invoke(meta)
 
-    val envelopeFormatFactories by lazy {
-        context.content<EnvelopeFormatFactory>(ENVELOPE_FORMAT_TYPE).values
+    public val envelopeFormatFactories: Collection<EnvelopeFormatFactory> by lazy {
+        context.gather<EnvelopeFormatFactory>(ENVELOPE_FORMAT_TYPE).values
     }
 
-    fun resolveEnvelopeFormat(name: Name, meta: Meta = Meta.EMPTY): EnvelopeFormat? =
+    private fun resolveEnvelopeFormat(name: Name, meta: Meta = Meta.EMPTY): EnvelopeFormat? =
         envelopeFormatFactories.find { it.name == name }?.invoke(meta, context)
 
-    fun resolveEnvelopeFormat(item: MetaItem<*>): EnvelopeFormat? {
+    public fun resolveEnvelopeFormat(item: MetaItem<*>): EnvelopeFormat? {
         val name = item.string ?: item.node[NAME_KEY]?.string ?: error("Envelope format name not defined")
         val meta = item.node[META_KEY].node ?: Meta.EMPTY
         return resolveEnvelopeFormat(name.toName(), meta)
     }
 
-    override fun provideTop(target: String): Map<Name, Any> {
+    override fun content(target: String): Map<Name, Any> {
         return when (target) {
             META_FORMAT_TYPE -> defaultMetaFormats.toMap()
             ENVELOPE_FORMAT_TYPE -> defaultEnvelopeFormats.toMap()
-            else -> super.provideTop(target)
+            else -> super.content(target)
         }
     }
 
-    companion object : PluginFactory<IOPlugin> {
-        val defaultMetaFormats: List<MetaFormatFactory> = listOf(JsonMetaFormat, BinaryMetaFormat)
-        val defaultEnvelopeFormats = listOf(TaggedEnvelopeFormat, TaglessEnvelopeFormat)
+    public companion object : PluginFactory<IOPlugin> {
+        public val defaultMetaFormats: List<MetaFormatFactory> = listOf(JsonMetaFormat, BinaryMetaFormat)
+        public val defaultEnvelopeFormats: List<EnvelopeFormatFactory> = listOf(TaggedEnvelopeFormat, TaglessEnvelopeFormat)
 
         override val tag: PluginTag = PluginTag("io", group = PluginTag.DATAFORGE_GROUP)
 
@@ -71,4 +71,4 @@ class IOPlugin(meta: Meta) : AbstractPlugin(meta) {
     }
 }
 
-val Context.io: IOPlugin get() = plugins.fetch(IOPlugin)
\ No newline at end of file
+public val Context.io: IOPlugin get() = plugins.fetch(IOPlugin)
\ No newline at end of file
diff --git a/dataforge-io/src/commonMain/kotlin/hep/dataforge/io/JsonMetaFormat.kt b/dataforge-io/src/commonMain/kotlin/hep/dataforge/io/JsonMetaFormat.kt
index e19a9f7d..2be2fe51 100644
--- a/dataforge-io/src/commonMain/kotlin/hep/dataforge/io/JsonMetaFormat.kt
+++ b/dataforge-io/src/commonMain/kotlin/hep/dataforge/io/JsonMetaFormat.kt
@@ -12,45 +12,46 @@ import hep.dataforge.meta.toJson
 import hep.dataforge.meta.toMetaItem
 import kotlinx.io.Input
 import kotlinx.io.Output
-import kotlinx.io.readByteArray
+import kotlinx.io.text.readUtf8String
 import kotlinx.io.text.writeUtf8String
-import kotlinx.serialization.UnstableDefault
 import kotlinx.serialization.json.Json
-import kotlinx.serialization.json.JsonObjectSerializer
+import kotlinx.serialization.json.JsonObject
 
-@OptIn(UnstableDefault::class)
-class JsonMetaFormat(private val json: Json = DEFAULT_JSON) : MetaFormat {
+/**
+ * A Json format for Meta representation
+ */
+public class JsonMetaFormat(private val json: Json = DEFAULT_JSON) : MetaFormat {
 
-    override fun Output.writeMeta(meta: Meta, descriptor: NodeDescriptor?) {
+    override fun writeMeta(output: Output, meta: Meta, descriptor: NodeDescriptor?) {
         val jsonObject = meta.toJson(descriptor)
-        writeUtf8String(json.stringify(JsonObjectSerializer, jsonObject))
+        output.writeUtf8String(json.encodeToString(JsonObject.serializer(), jsonObject))
     }
 
-    override fun toMeta(): Meta  = Meta{
+    override fun toMeta(): Meta = Meta {
         NAME_KEY put name.toString()
     }
 
-    override fun Input.readMeta(descriptor: NodeDescriptor?): Meta {
-        val str = readByteArray().decodeToString()
-        val jsonElement = json.parseJson(str)
+    override fun readMeta(input: Input, descriptor: NodeDescriptor?): Meta {
+        val str = input.readUtf8String()//readByteArray().decodeToString()
+        val jsonElement = json.parseToJsonElement(str)
         val item = jsonElement.toMetaItem(descriptor)
         return item.node ?: Meta.EMPTY
     }
 
-    companion object : MetaFormatFactory {
-        val DEFAULT_JSON = Json { prettyPrint = true }
+    public companion object : MetaFormatFactory {
+        public val DEFAULT_JSON: Json = Json { prettyPrint = true }
 
         override fun invoke(meta: Meta, context: Context): MetaFormat = default
 
-        override val shortName = "json"
+        override val shortName: String = "json"
         override val key: Short = 0x4a53//"JS"
 
         private val default = JsonMetaFormat()
 
-        override fun Output.writeMeta(meta: Meta, descriptor: NodeDescriptor?) =
-            default.run { writeMeta(meta, descriptor) }
+        override fun writeMeta(output: Output, meta: Meta, descriptor: NodeDescriptor?): Unit =
+            default.run { writeMeta(output, meta, descriptor) }
 
-        override fun Input.readMeta(descriptor: NodeDescriptor?): Meta =
-            default.run { readMeta(descriptor) }
+        override fun readMeta(input: Input, descriptor: NodeDescriptor?): Meta =
+            default.run { readMeta(input, descriptor) }
     }
 }
diff --git a/dataforge-io/src/commonMain/kotlin/hep/dataforge/io/MetaFormat.kt b/dataforge-io/src/commonMain/kotlin/hep/dataforge/io/MetaFormat.kt
index 4b893a4a..f3e26d2a 100644
--- a/dataforge-io/src/commonMain/kotlin/hep/dataforge/io/MetaFormat.kt
+++ b/dataforge-io/src/commonMain/kotlin/hep/dataforge/io/MetaFormat.kt
@@ -17,46 +17,50 @@ import kotlin.reflect.KClass
 /**
  * A format for meta serialization
  */
+public interface MetaFormat : IOFormat<Meta> {
 
-interface MetaFormat : IOFormat<Meta> {
-
-    override fun Output.writeObject(obj: Meta) {
-        writeMeta(obj, null)
+    override fun writeObject(output: Output, obj: Meta) {
+        writeMeta(output, obj, null)
     }
 
-    override fun Input.readObject(): Meta = readMeta()
+    override fun readObject(input: Input): Meta = readMeta(input)
 
-    fun Output.writeMeta(meta: Meta, descriptor: NodeDescriptor? = null)
-    fun Input.readMeta(descriptor: NodeDescriptor? = null): Meta
+    public fun writeMeta(
+        output: Output,
+        meta: Meta,
+        descriptor: NodeDescriptor? = null,
+    )
+
+    public fun readMeta(input: Input, descriptor: NodeDescriptor? = null): Meta
 }
 
 @Type(META_FORMAT_TYPE)
-interface MetaFormatFactory : IOFormatFactory<Meta>, MetaFormat {
-    val shortName: String
+public interface MetaFormatFactory : IOFormatFactory<Meta>, MetaFormat {
+    public val shortName: String
 
     override val name: Name get() = "meta".asName() + shortName
 
     override val type: KClass<out Meta> get() = Meta::class
 
-    val key: Short get() = name.hashCode().toShort()
+    public val key: Short get() = name.hashCode().toShort()
 
     override operator fun invoke(meta: Meta, context: Context): MetaFormat
 
-    companion object {
-        const val META_FORMAT_TYPE = "io.format.meta"
+    public companion object {
+        public const val META_FORMAT_TYPE: String = "io.format.meta"
     }
 }
 
-fun Meta.toString(format: MetaFormat): String = buildByteArray {
-    format.run { writeObject(this@toString) }
+public fun Meta.toString(format: MetaFormat): String = buildByteArray {
+    format.run { writeObject(this@buildByteArray, this@toString) }
 }.decodeToString()
 
-fun Meta.toString(formatFactory: MetaFormatFactory): String = toString(formatFactory())
+public fun Meta.toString(formatFactory: MetaFormatFactory): String = toString(formatFactory())
 
-fun MetaFormat.parse(str: String): Meta {
-    return ByteArrayInput(str.encodeToByteArray()).use { it.readObject() }
+public fun MetaFormat.parse(str: String): Meta {
+    return ByteArrayInput(str.encodeToByteArray()).use { readObject(it) }
 }
 
-fun MetaFormatFactory.parse(str: String, formatMeta: Meta): Meta = invoke(formatMeta).parse(str)
+public fun MetaFormatFactory.parse(str: String, formatMeta: Meta): Meta = invoke(formatMeta).parse(str)
 
 
diff --git a/dataforge-io/src/commonMain/kotlin/hep/dataforge/io/Responder.kt b/dataforge-io/src/commonMain/kotlin/hep/dataforge/io/Responder.kt
index e3545782..2710ffa9 100644
--- a/dataforge-io/src/commonMain/kotlin/hep/dataforge/io/Responder.kt
+++ b/dataforge-io/src/commonMain/kotlin/hep/dataforge/io/Responder.kt
@@ -1,8 +1,12 @@
 package hep.dataforge.io
 
-interface Responder {
+/**
+ * An object that could respond to external messages asynchronously
+ */
+public interface Responder {
     /**
      * Send a request and wait for response for this specific request
      */
-    suspend fun respond(request: Envelope): Envelope
-}
\ No newline at end of file
+    public suspend fun respond(request: Envelope): Envelope
+}
+
diff --git a/dataforge-io/src/commonMain/kotlin/hep/dataforge/io/TaggedEnvelopeFormat.kt b/dataforge-io/src/commonMain/kotlin/hep/dataforge/io/TaggedEnvelopeFormat.kt
index ebcca243..389c5054 100644
--- a/dataforge-io/src/commonMain/kotlin/hep/dataforge/io/TaggedEnvelopeFormat.kt
+++ b/dataforge-io/src/commonMain/kotlin/hep/dataforge/io/TaggedEnvelopeFormat.kt
@@ -12,9 +12,13 @@ import hep.dataforge.names.plus
 import hep.dataforge.names.toName
 import kotlinx.io.*
 
-class TaggedEnvelopeFormat(
-    val io: IOPlugin,
-    val version: VERSION = VERSION.DF02
+/**
+ * A streaming-friendly envelope format with a short binary tag.
+ * TODO add description
+ */
+public class TaggedEnvelopeFormat(
+    public val io: IOPlugin,
+    public val version: VERSION = VERSION.DF02,
 ) : EnvelopeFormat {
 
 //    private val metaFormat = io.metaFormat(metaFormatKey)
@@ -37,18 +41,23 @@ class TaggedEnvelopeFormat(
         writeRawString(END_SEQUENCE)
     }
 
-    override fun Output.writeEnvelope(envelope: Envelope, metaFormatFactory: MetaFormatFactory, formatMeta: Meta) {
-        val metaFormat = metaFormatFactory.invoke(formatMeta, io.context)
+    override fun writeEnvelope(
+        output: Output,
+        envelope: Envelope,
+        metaFormatFactory: MetaFormatFactory,
+        formatMeta: Meta,
+    ) {
+        val metaFormat = metaFormatFactory.invoke(formatMeta, this@TaggedEnvelopeFormat.io.context)
         val metaBytes = metaFormat.toBinary(envelope.meta)
         val actualSize: ULong = (envelope.data?.size ?: 0).toULong()
         val tag = Tag(metaFormatFactory.key, metaBytes.size.toUInt() + 2u, actualSize)
-        writeBinary(tag.toBinary())
-        writeBinary(metaBytes)
-        writeRawString("\r\n")
+        output.writeBinary(tag.toBinary())
+        output.writeBinary(metaBytes)
+        output.writeRawString("\r\n")
         envelope.data?.let {
-            writeBinary(it)
+            output.writeBinary(it)
         }
-        flush()
+        output.flush()
     }
 
     /**
@@ -57,34 +66,27 @@ class TaggedEnvelopeFormat(
      * @param input an input to read from
      * @param formats a collection of meta formats to resolve
      */
-    override fun Input.readObject(): Envelope {
-        val tag = readTag(version)
+    override fun readObject(input: Input): Envelope {
+        val tag = input.readTag(this.version)
 
         val metaFormat = io.resolveMetaFormat(tag.metaFormatKey)
             ?: error("Meta format with key ${tag.metaFormatKey} not found")
 
-        val meta: Meta = limit(tag.metaSize.toInt()).run {
-            metaFormat.run {
-                readObject()
-            }
-        }
+        val meta: Meta = metaFormat.readObject(input.limit(tag.metaSize.toInt()))
 
-        val data = readBinary(tag.dataSize.toInt())
+        val data = input.readBinary(tag.dataSize.toInt())
 
         return SimpleEnvelope(meta, data)
     }
 
-    override fun Input.readPartial(): PartialEnvelope {
-        val tag = readTag(version)
+    override fun readPartial(input: Input): PartialEnvelope {
+        val tag = input.readTag(this.version)
 
         val metaFormat = io.resolveMetaFormat(tag.metaFormatKey)
             ?: error("Meta format with key ${tag.metaFormatKey} not found")
 
-        val meta: Meta = limit(tag.metaSize.toInt()).run {
-            metaFormat.run {
-                readObject()
-            }
-        }
+        val meta: Meta = metaFormat.readObject(input.limit(tag.metaSize.toInt()))
+
 
         return PartialEnvelope(meta, version.tagSize + tag.metaSize, tag.dataSize)
     }
@@ -92,10 +94,10 @@ class TaggedEnvelopeFormat(
     private data class Tag(
         val metaFormatKey: Short,
         val metaSize: UInt,
-        val dataSize: ULong
+        val dataSize: ULong,
     )
 
-    enum class VERSION(val tagSize: UInt) {
+    public enum class VERSION(public val tagSize: UInt) {
         DF02(20u),
         DF03(24u)
     }
@@ -107,7 +109,7 @@ class TaggedEnvelopeFormat(
         }
     }
 
-    companion object : EnvelopeFormatFactory {
+    public companion object : EnvelopeFormatFactory {
         private const val START_SEQUENCE = "#~"
         private const val END_SEQUENCE = "~#\r\n"
 
@@ -158,16 +160,24 @@ class TaggedEnvelopeFormat(
 
         private val default by lazy { invoke() }
 
-        override fun Input.readPartial(): PartialEnvelope =
-            default.run { readPartial() }
-
-        override fun Output.writeEnvelope(envelope: Envelope, metaFormatFactory: MetaFormatFactory, formatMeta: Meta) =
-            default.run { writeEnvelope(envelope, metaFormatFactory, formatMeta) }
-
-        override fun Input.readObject(): Envelope =
-            default.run { readObject() }
+        override fun readPartial(input: Input): PartialEnvelope =
+            default.run { readPartial(input) }
 
+        override fun writeEnvelope(
+            output: Output,
+            envelope: Envelope,
+            metaFormatFactory: MetaFormatFactory,
+            formatMeta: Meta,
+        ): Unit = default.run {
+            writeEnvelope(
+                output,
+                envelope,
+                metaFormatFactory,
+                formatMeta
+            )
+        }
 
+        override fun readObject(input: Input): Envelope = default.readObject(input)
     }
 
 }
\ No newline at end of file
diff --git a/dataforge-io/src/commonMain/kotlin/hep/dataforge/io/TaglessEnvelopeFormat.kt b/dataforge-io/src/commonMain/kotlin/hep/dataforge/io/TaglessEnvelopeFormat.kt
index c800d878..f89f9bbb 100644
--- a/dataforge-io/src/commonMain/kotlin/hep/dataforge/io/TaglessEnvelopeFormat.kt
+++ b/dataforge-io/src/commonMain/kotlin/hep/dataforge/io/TaglessEnvelopeFormat.kt
@@ -7,15 +7,20 @@ import hep.dataforge.meta.Meta
 import hep.dataforge.meta.get
 import hep.dataforge.meta.isEmpty
 import hep.dataforge.meta.string
+import hep.dataforge.names.Name
 import hep.dataforge.names.asName
 import kotlinx.io.*
 import kotlinx.io.text.readUtf8Line
 import kotlinx.io.text.writeUtf8String
 import kotlin.collections.set
 
-class TaglessEnvelopeFormat(
-    val io: IOPlugin,
-    val meta: Meta = Meta.EMPTY
+/**
+ * A text envelope format with human-readable tag.
+ * TODO add description
+ */
+public class TaglessEnvelopeFormat(
+    public val io: IOPlugin,
+    public val meta: Meta = Meta.EMPTY,
 ) : EnvelopeFormat {
 
     private val metaStart = meta[META_START_PROPERTY].string ?: DEFAULT_META_START
@@ -25,39 +30,46 @@ class TaglessEnvelopeFormat(
         writeUtf8String("#? $key: $value;\r\n")
     }
 
-    override fun Output.writeEnvelope(envelope: Envelope, metaFormatFactory: MetaFormatFactory, formatMeta: Meta) {
-        val metaFormat = metaFormatFactory(formatMeta, io.context)
+    override fun writeEnvelope(
+        output: Output,
+        envelope: Envelope,
+        metaFormatFactory: MetaFormatFactory,
+        formatMeta: Meta
+    ) {
+        val metaFormat = metaFormatFactory(formatMeta, this.io.context)
 
         //printing header
-        writeRawString(TAGLESS_ENVELOPE_HEADER + "\r\n")
+        output.writeRawString(TAGLESS_ENVELOPE_HEADER + "\r\n")
 
         //printing all properties
-        writeProperty(META_TYPE_PROPERTY, metaFormatFactory.shortName)
+        output.writeProperty(META_TYPE_PROPERTY,
+            metaFormatFactory.shortName)
         //TODO add optional metaFormat properties
         val actualSize: Int = envelope.data?.size ?: 0
 
-        writeProperty(DATA_LENGTH_PROPERTY, actualSize)
+        output.writeProperty(DATA_LENGTH_PROPERTY, actualSize)
 
         //Printing meta
         if (!envelope.meta.isEmpty()) {
             val metaBytes = metaFormat.toBinary(envelope.meta)
-            writeProperty(META_LENGTH_PROPERTY, metaBytes.size + 2)
-            writeUtf8String(metaStart + "\r\n")
-            writeBinary(metaBytes)
-            writeRawString("\r\n")
+            output.writeProperty(META_LENGTH_PROPERTY,
+                metaBytes.size + 2)
+            output.writeUtf8String(this.metaStart + "\r\n")
+            output.writeBinary(metaBytes)
+            output.writeRawString("\r\n")
         }
 
         //Printing data
         envelope.data?.let { data ->
-            writeUtf8String(dataStart + "\r\n")
-            writeBinary(data)
+            output.writeUtf8String(this.dataStart + "\r\n")
+            output.writeBinary(data)
         }
     }
 
-    override fun Input.readObject(): Envelope {
+    override fun readObject(input: Input): Envelope {
         var line: String
         do {
-            line = readUtf8Line() // ?: error("Input does not contain tagless envelope header")
+            line = input.readUtf8Line() // ?: error("Input does not contain tagless envelope header")
         } while (!line.startsWith(TAGLESS_ENVELOPE_HEADER))
         val properties = HashMap<String, String>()
 
@@ -70,8 +82,8 @@ class TaglessEnvelopeFormat(
                 properties[key] = value
             }
             //If can't read line, return envelope without data
-            if (exhausted()) return SimpleEnvelope(Meta.EMPTY, null)
-            line = readUtf8Line()
+            if (input.exhausted()) return SimpleEnvelope(Meta.EMPTY, null)
+            line = input.readUtf8Line()
         }
 
         var meta: Meta = Meta.EMPTY
@@ -80,19 +92,15 @@ class TaglessEnvelopeFormat(
             val metaFormat = properties[META_TYPE_PROPERTY]?.let { io.resolveMetaFormat(it) } ?: JsonMetaFormat
             val metaSize = properties[META_LENGTH_PROPERTY]?.toInt()
             meta = if (metaSize != null) {
-                limit(metaSize).run {
-                    metaFormat.run { readObject() }
-                }
+                metaFormat.readObject(input.limit(metaSize))
             } else {
-                metaFormat.run {
-                    readObject()
-                }
+                metaFormat.readObject(input)
             }
         }
 
         do {
             try {
-                line = readUtf8Line()
+                line = input.readUtf8Line()
             } catch (ex: EOFException) {
                 //returning an Envelope without data if end of input is reached
                 return SimpleEnvelope(meta, null)
@@ -100,24 +108,24 @@ class TaglessEnvelopeFormat(
         } while (!line.startsWith(dataStart))
 
         val data: Binary? = if (properties.containsKey(DATA_LENGTH_PROPERTY)) {
-            readBinary(properties[DATA_LENGTH_PROPERTY]!!.toInt())
+            input.readBinary(properties[DATA_LENGTH_PROPERTY]!!.toInt())
 //            val bytes = ByteArray(properties[DATA_LENGTH_PROPERTY]!!.toInt())
 //            readByteArray(bytes)
 //            bytes.asBinary()
         } else {
             Binary {
-                copyTo(this)
+                input.copyTo(this)
             }
         }
 
         return SimpleEnvelope(meta, data)
     }
 
-    override fun Input.readPartial(): PartialEnvelope {
+    override fun readPartial(input: Input): PartialEnvelope {
         var offset = 0u
         var line: String
         do {
-            line = readUtf8Line()// ?: error("Input does not contain tagless envelope header")
+            line = input.readUtf8Line()// ?: error("Input does not contain tagless envelope header")
             offset += line.encodeToByteArray().size.toUInt()
         } while (!line.startsWith(TAGLESS_ENVELOPE_HEADER))
         val properties = HashMap<String, String>()
@@ -131,7 +139,7 @@ class TaglessEnvelopeFormat(
                 properties[key] = value
             }
             try {
-                line = readUtf8Line()
+                line = input.readUtf8Line()
                 offset += line.encodeToByteArray().size.toUInt()
             } catch (ex: EOFException) {
                 return PartialEnvelope(Meta.EMPTY, offset.toUInt(), 0.toULong())
@@ -145,16 +153,14 @@ class TaglessEnvelopeFormat(
             val metaSize = properties[META_LENGTH_PROPERTY]?.toInt()
             meta = if (metaSize != null) {
                 offset += metaSize.toUInt()
-                limit(metaSize).run {
-                    metaFormat.run { readObject() }
-                }
+                metaFormat.readObject(input.limit(metaSize))
             } else {
                 error("Can't partially read an envelope with undefined meta size")
             }
         }
 
         do {
-            line = readUtf8Line() //?: return PartialEnvelope(Meta.EMPTY, offset.toUInt(), 0.toULong())
+            line = input.readUtf8Line() //?: return PartialEnvelope(Meta.EMPTY, offset.toUInt(), 0.toULong())
             offset += line.encodeToByteArray().size.toUInt()
             //returning an Envelope without data if end of input is reached
         } while (!line.startsWith(dataStart))
@@ -168,26 +174,26 @@ class TaglessEnvelopeFormat(
         META_KEY put meta
     }
 
-    companion object : EnvelopeFormatFactory {
+    public companion object : EnvelopeFormatFactory {
 
-        private val propertyPattern = "#\\?\\s*(?<key>[\\w.]*)\\s*:\\s*(?<value>[^;]*);?".toRegex()
+        private val propertyPattern = "#\\?\\s*([\\w.]*)\\s*:\\s*([^;]*);?".toRegex()
 
-        const val META_TYPE_PROPERTY = "metaType"
-        const val META_LENGTH_PROPERTY = "metaLength"
-        const val DATA_LENGTH_PROPERTY = "dataLength"
+        public const val META_TYPE_PROPERTY: String = "metaType"
+        public const val META_LENGTH_PROPERTY: String = "metaLength"
+        public const val DATA_LENGTH_PROPERTY: String = "dataLength"
 
 
-        const val TAGLESS_ENVELOPE_TYPE = "tagless"
+        public const val TAGLESS_ENVELOPE_TYPE: String = "tagless"
 
-        const val TAGLESS_ENVELOPE_HEADER = "#~DFTL~#"
-        const val META_START_PROPERTY = "metaSeparator"
-        const val DEFAULT_META_START = "#~META~#"
-        const val DATA_START_PROPERTY = "dataSeparator"
-        const val DEFAULT_DATA_START = "#~DATA~#"
+        public const val TAGLESS_ENVELOPE_HEADER: String = "#~DFTL~#"
+        public const val META_START_PROPERTY: String = "metaSeparator"
+        public const val DEFAULT_META_START: String = "#~META~#"
+        public const val DATA_START_PROPERTY: String = "dataSeparator"
+        public const val DEFAULT_DATA_START: String = "#~DATA~#"
 
-        const val code: Int = 0x4446544c //DFTL
+        public const val code: Int = 0x4446544c //DFTL
 
-        override val name = TAGLESS_ENVELOPE_TYPE.asName()
+        override val name: Name = TAGLESS_ENVELOPE_TYPE.asName()
 
         override fun invoke(meta: Meta, context: Context): EnvelopeFormat {
             return TaglessEnvelopeFormat(context.io, meta)
@@ -195,14 +201,24 @@ class TaglessEnvelopeFormat(
 
         private val default by lazy { invoke() }
 
-        override fun Input.readPartial(): PartialEnvelope =
-            default.run { readPartial() }
+        override fun readPartial(input: Input): PartialEnvelope =
+            default.run { readPartial(input) }
 
-        override fun Output.writeEnvelope(envelope: Envelope, metaFormatFactory: MetaFormatFactory, formatMeta: Meta) =
-            default.run { writeEnvelope(envelope, metaFormatFactory, formatMeta) }
+        override fun writeEnvelope(
+            output: Output,
+            envelope: Envelope,
+            metaFormatFactory: MetaFormatFactory,
+            formatMeta: Meta,
+        ): Unit = default.run {
+            writeEnvelope(
+                output,
+                envelope,
+                metaFormatFactory,
+                formatMeta
+            )
+        }
 
-        override fun Input.readObject(): Envelope =
-            default.run { readObject() }
+        override fun readObject(input: Input): Envelope = default.readObject(input)
 
         override fun peekFormat(io: IOPlugin, input: Input): EnvelopeFormat? {
             return try {
diff --git a/dataforge-io/src/commonMain/kotlin/hep/dataforge/io/functions/FunctionServer.kt b/dataforge-io/src/commonMain/kotlin/hep/dataforge/io/functions/FunctionServer.kt
deleted file mode 100644
index 2eca605c..00000000
--- a/dataforge-io/src/commonMain/kotlin/hep/dataforge/io/functions/FunctionServer.kt
+++ /dev/null
@@ -1,75 +0,0 @@
-package hep.dataforge.io.functions
-
-import hep.dataforge.context.ContextAware
-import hep.dataforge.io.IOFormat
-import hep.dataforge.io.IOPlugin
-import hep.dataforge.meta.Meta
-import hep.dataforge.meta.get
-import hep.dataforge.names.asName
-import hep.dataforge.names.plus
-import kotlin.reflect.KClass
-
-
-/**
- * A server that could produce asynchronous function values
- */
-interface FunctionServer : ContextAware {
-    /**
-     * Call a function with given name and descriptor
-     */
-    suspend fun <T : Any, R : Any> call(meta: Meta, arg: T, inputType: KClass<out T>, outputType: KClass<out R>): R
-
-    suspend fun <T : Any, R : Any> callMany(
-        meta: Meta,
-        arg: List<T>,
-        inputType: KClass<out T>,
-        outputType: KClass<out R>
-    ): List<R> = List(arg.size) {
-        call<T, R>(meta, arg[it], inputType, outputType)
-    }
-
-    /**
-     * Get a generic suspended function with given name and descriptor
-     */
-    fun <T : Any, R : Any> function(
-        meta: Meta,
-        inputType: KClass<out T>,
-        outputType: KClass<out R>
-    ): (suspend (T) -> R) = { call(meta, it, inputType, outputType) }
-
-    companion object {
-        const val FUNCTION_NAME_KEY = "function"
-        val FORMAT_KEY = "format".asName()
-        val INPUT_FORMAT_KEY = FORMAT_KEY + "input"
-        val OUTPUT_FORMAT_KEY = FORMAT_KEY + "output"
-    }
-}
-
-suspend inline fun <reified T : Any, reified R : Any> FunctionServer.call(meta: Meta, arg: T) =
-    call(meta, arg, T::class, R::class)
-
-suspend inline fun <reified T : Any, reified R : Any> FunctionServer.callMany(meta: Meta, arg: List<T>) =
-    callMany(meta, arg, T::class, R::class)
-
-inline fun <reified T : Any, reified R : Any> FunctionServer.function(meta: Meta) =
-    function(meta, T::class, R::class)
-
-fun <T : Any> IOPlugin.getInputFormat(meta: Meta, type: KClass<out T>): IOFormat<T> {
-    return meta[FunctionServer.INPUT_FORMAT_KEY]?.let {
-        resolveIOFormat<T>(it, type)
-    } ?: error("Input format not resolved")
-}
-
-fun <R : Any> IOPlugin.getOutputFormat(meta: Meta, type: KClass<out R>): IOFormat<R> {
-    return meta[FunctionServer.OUTPUT_FORMAT_KEY]?.let {
-        resolveIOFormat<R>(it, type)
-    } ?: error("Input format not resolved")
-}
-
-inline fun <reified T : Any> IOPlugin.getInputFormat(meta: Meta): IOFormat<T> =
-    getInputFormat(meta, T::class)
-
-inline fun <reified R : Any> IOPlugin.getOutputFormat(meta: Meta): IOFormat<R> =
-    getOutputFormat(meta, R::class)
-
-
diff --git a/dataforge-io/src/commonMain/kotlin/hep/dataforge/io/functions/RemoteFunctionClient.kt b/dataforge-io/src/commonMain/kotlin/hep/dataforge/io/functions/RemoteFunctionClient.kt
deleted file mode 100644
index 7c294891..00000000
--- a/dataforge-io/src/commonMain/kotlin/hep/dataforge/io/functions/RemoteFunctionClient.kt
+++ /dev/null
@@ -1,98 +0,0 @@
-package hep.dataforge.io.functions
-
-import hep.dataforge.context.Context
-import hep.dataforge.context.ContextAware
-import hep.dataforge.io.*
-import hep.dataforge.meta.Meta
-import hep.dataforge.meta.get
-import hep.dataforge.meta.int
-import kotlin.reflect.KClass
-
-class RemoteFunctionClient(override val context: Context, val responder: Responder) : FunctionServer, ContextAware {
-
-    private fun <T : Any> IOPlugin.encodeOne(
-        meta: Meta,
-        value: T,
-        valueType: KClass<out T> = value::class
-    ): Envelope = Envelope.invoke {
-        meta(meta)
-        type = REQUEST_TYPE
-        data {
-            val inputFormat: IOFormat<T> = getInputFormat(meta, valueType)
-            inputFormat.run {
-                writeObject(value)
-            }
-        }
-    }
-
-    private fun <T : Any> IOPlugin.encodeMany(
-        meta: Meta,
-        values: List<T>,
-        valueType: KClass<out T>
-    ): Envelope = Envelope.invoke {
-        meta(meta)
-        type = REQUEST_TYPE
-        meta {
-            SIZE_KEY put values.size
-        }
-        data {
-            val inputFormat: IOFormat<T> = getInputFormat(meta, valueType)
-            inputFormat.run {
-                values.forEach {
-                    writeObject(it)
-                }
-            }
-        }
-    }
-
-    private fun <R : Any> IOPlugin.decode(envelope: Envelope, valueType: KClass<out R>): List<R> {
-        require(envelope.type == RESPONSE_TYPE) { "Unexpected message type: ${envelope.type}" }
-        val size = envelope.meta[SIZE_KEY].int ?: 1
-
-        return if (size == 0) {
-            emptyList()
-        } else {
-            val outputFormat: IOFormat<R> = getOutputFormat(envelope.meta, valueType)
-            envelope.data?.read {
-                List<R>(size) {
-                    outputFormat.run {
-                        readObject()
-                    }
-                }
-            } ?: error("Message does not contain data")
-        }
-    }
-
-    private val plugin by lazy {
-        context.plugins.load(IOPlugin)
-    }
-
-    override suspend fun <T : Any, R : Any> call(
-        meta: Meta,
-        arg: T,
-        inputType: KClass<out T>,
-        outputType: KClass<out R>
-    ): R = plugin.run {
-        val request = encodeOne(meta, arg)
-        val response = responder.respond(request)
-        return decode<R>(response, outputType).first()
-    }
-
-    override suspend fun <T : Any, R : Any> callMany(
-        meta: Meta,
-        arg: List<T>,
-        inputType: KClass<out T>,
-        outputType: KClass<out R>
-    ): List<R> = plugin.run {
-        val request = encodeMany(meta, arg, inputType)
-        val response = responder.respond(request)
-        return decode<R>(response, outputType)
-    }
-
-    companion object {
-        const val REQUEST_TYPE = "function.request"
-        const val RESPONSE_TYPE = "function.response"
-
-        const val SIZE_KEY = "size"
-    }
-}
\ No newline at end of file
diff --git a/dataforge-io/src/commonMain/kotlin/hep/dataforge/io/functions/RemoteFunctionServer.kt b/dataforge-io/src/commonMain/kotlin/hep/dataforge/io/functions/RemoteFunctionServer.kt
deleted file mode 100644
index 8252b1d3..00000000
--- a/dataforge-io/src/commonMain/kotlin/hep/dataforge/io/functions/RemoteFunctionServer.kt
+++ /dev/null
@@ -1,58 +0,0 @@
-package hep.dataforge.io.functions
-
-import hep.dataforge.context.Context
-import hep.dataforge.context.ContextAware
-import hep.dataforge.io.Envelope
-import hep.dataforge.io.IOPlugin
-import hep.dataforge.io.Responder
-import hep.dataforge.io.type
-import hep.dataforge.meta.get
-import hep.dataforge.meta.int
-
-class RemoteFunctionServer(
-    override val context: Context,
-    val functionServer: FunctionServer
-) : ContextAware, Responder {
-
-    private val plugin by lazy {
-        context.plugins.load(IOPlugin)
-    }
-
-
-    override suspend fun respond(request: Envelope): Envelope {
-        require(request.type == RemoteFunctionClient.REQUEST_TYPE) { "Unexpected message type: ${request.type}" }
-
-        val inputFormat = plugin.getInputFormat<Any>(request.meta)
-        val outputFormat = plugin.getOutputFormat<Any>(request.meta)
-
-        val size = request.meta[RemoteFunctionClient.SIZE_KEY].int ?: 1
-
-        val input = request.data?.read {
-            inputFormat.run {
-                List(size) {
-                    readObject()
-                }
-            }
-        } ?: error("Input is empty")
-
-        val output = functionServer.callMany<Any, Any>(
-            request.meta,
-            input
-        )
-
-        return Envelope.invoke {
-            meta {
-                meta(request.meta)
-            }
-            type = RemoteFunctionClient.RESPONSE_TYPE
-            data {
-                outputFormat.run {
-                    output.forEach {
-                        writeObject(it)
-                    }
-                }
-            }
-
-        }
-    }
-}
\ No newline at end of file
diff --git a/dataforge-io/src/commonMain/kotlin/hep/dataforge/io/ioMisc.kt b/dataforge-io/src/commonMain/kotlin/hep/dataforge/io/ioMisc.kt
index 9b214c5c..283f7638 100644
--- a/dataforge-io/src/commonMain/kotlin/hep/dataforge/io/ioMisc.kt
+++ b/dataforge-io/src/commonMain/kotlin/hep/dataforge/io/ioMisc.kt
@@ -3,26 +3,26 @@ package hep.dataforge.io
 import kotlinx.io.*
 import kotlin.math.min
 
-fun Output.writeRawString(str: String) {
+public fun Output.writeRawString(str: String) {
     str.forEach { writeByte(it.toByte()) }
 }
 
-fun Input.readRawString(size: Int): String {
+public fun Input.readRawString(size: Int): String {
     val array = CharArray(size) { readByte().toChar() }
-    return String(array)
+    return array.concatToString()
 }
 
-inline fun buildByteArray(expectedSize: Int = 16, block: Output.() -> Unit): ByteArray =
+public inline fun buildByteArray(expectedSize: Int = 16, block: Output.() -> Unit): ByteArray =
     ByteArrayOutput(expectedSize).apply(block).toByteArray()
 
 @Suppress("FunctionName")
-inline fun Binary(expectedSize: Int = 16, block: Output.() -> Unit): Binary =
+public inline fun Binary(expectedSize: Int = 16, block: Output.() -> Unit): Binary =
     buildByteArray(expectedSize, block).asBinary()
 
 /**
  * View section of a [Binary] as an independent binary
  */
-class BinaryView(private val source: Binary, private val start: Int, override val size: Int) : Binary {
+public class BinaryView(private val source: Binary, private val start: Int, override val size: Int) : Binary {
 
     init {
         require(start > 0)
@@ -34,6 +34,6 @@ class BinaryView(private val source: Binary, private val start: Int, override va
     }
 }
 
-fun Binary.view(start: Int, size: Int) = BinaryView(this, start, size)
+public fun Binary.view(start: Int, size: Int): BinaryView = BinaryView(this, start, size)
 
-operator fun Binary.get(range: IntRange) = view(range.first, range.last - range.first)
\ No newline at end of file
+public operator fun Binary.get(range: IntRange): BinaryView = view(range.first, range.last - range.first)
\ No newline at end of file
diff --git a/dataforge-io/src/commonTest/kotlin/hep/dataforge/io/EnvelopeFormatTest.kt b/dataforge-io/src/commonTest/kotlin/hep/dataforge/io/EnvelopeFormatTest.kt
index 0fd09abf..8bcc54cd 100644
--- a/dataforge-io/src/commonTest/kotlin/hep/dataforge/io/EnvelopeFormatTest.kt
+++ b/dataforge-io/src/commonTest/kotlin/hep/dataforge/io/EnvelopeFormatTest.kt
@@ -23,9 +23,9 @@ class EnvelopeFormatTest {
     @Test
     fun testTaggedFormat(){
         TaggedEnvelopeFormat.run {
-            val byteArray = this.toByteArray(envelope)
+            val byteArray = writeToByteArray(envelope)
             //println(byteArray.decodeToString())
-            val res = readByteArray(byteArray)
+            val res = readFromByteArray(byteArray)
             assertEquals(envelope.meta,res.meta)
             val double = res.data?.read {
                 readDouble()
@@ -37,9 +37,9 @@ class EnvelopeFormatTest {
     @Test
     fun testTaglessFormat(){
         TaglessEnvelopeFormat.run {
-            val byteArray = toByteArray(envelope)
+            val byteArray = writeToByteArray(envelope)
             //println(byteArray.decodeToString())
-            val res = readByteArray(byteArray)
+            val res = readFromByteArray(byteArray)
             assertEquals(envelope.meta,res.meta)
             val double = res.data?.read {
                 readDouble()
diff --git a/dataforge-io/src/commonTest/kotlin/hep/dataforge/io/MetaFormatTest.kt b/dataforge-io/src/commonTest/kotlin/hep/dataforge/io/MetaFormatTest.kt
index a470cf0a..cb8ba54b 100644
--- a/dataforge-io/src/commonTest/kotlin/hep/dataforge/io/MetaFormatTest.kt
+++ b/dataforge-io/src/commonTest/kotlin/hep/dataforge/io/MetaFormatTest.kt
@@ -3,18 +3,16 @@ package hep.dataforge.io
 import hep.dataforge.meta.*
 import hep.dataforge.meta.JsonMeta.Companion.JSON_ARRAY_KEY
 import kotlinx.io.asBinary
-import kotlinx.serialization.json.JsonPrimitive
-import kotlinx.serialization.json.json
-import kotlinx.serialization.json.jsonArray
+import kotlinx.serialization.json.*
 import kotlin.test.Test
 import kotlin.test.assertEquals
 
 fun Meta.toByteArray(format: MetaFormat = JsonMetaFormat) = buildByteArray {
-    format.run { writeObject(this@toByteArray) }
+    format.writeObject(this@buildByteArray, this@toByteArray)
 }
 
 fun MetaFormat.fromByteArray(packet: ByteArray): Meta {
-    return packet.asBinary().read { readObject() }
+    return packet.asBinary().read { readObject(this) }
 }
 
 class MetaFormatTest {
@@ -57,21 +55,21 @@ class MetaFormatTest {
 
     @Test
     fun testJsonToMeta() {
-        val json = jsonArray {
+        val json = buildJsonArray {
             //top level array
-            +jsonArray {
-                +JsonPrimitive(88)
-                +json {
-                    "c" to "aasdad"
-                    "d" to true
-                }
-            }
-            +"value"
-            +jsonArray {
-                +JsonPrimitive(1.0)
-                +JsonPrimitive(2.0)
-                +JsonPrimitive(3.0)
-            }
+            add(buildJsonArray {
+                add(JsonPrimitive(88))
+                add(buildJsonObject {
+                    put("c", "aasdad")
+                    put("d", true)
+                })
+            })
+            add("value")
+            add(buildJsonArray {
+                add(JsonPrimitive(1.0))
+                add(JsonPrimitive(2.0))
+                add(JsonPrimitive(3.0))
+            })
         }
         val meta = json.toMetaItem().node!!
 
diff --git a/dataforge-io/src/commonTest/kotlin/hep/dataforge/io/MetaSerializerTest.kt b/dataforge-io/src/commonTest/kotlin/hep/dataforge/io/MetaSerializerTest.kt
index dc8e5016..23fef5d5 100644
--- a/dataforge-io/src/commonTest/kotlin/hep/dataforge/io/MetaSerializerTest.kt
+++ b/dataforge-io/src/commonTest/kotlin/hep/dataforge/io/MetaSerializerTest.kt
@@ -1,12 +1,19 @@
 package hep.dataforge.io
 
-import hep.dataforge.meta.*
+import hep.dataforge.meta.Meta
+import hep.dataforge.meta.MetaItem
+import hep.dataforge.meta.MetaSerializer
 import hep.dataforge.names.Name
 import hep.dataforge.names.toName
+import kotlinx.serialization.ExperimentalSerializationApi
 import kotlinx.serialization.cbor.Cbor
+import kotlinx.serialization.json.Json
 import kotlin.test.Test
 import kotlin.test.assertEquals
 
+val JSON_PRETTY: Json = Json { prettyPrint = true; useArrayPolymorphism = true }
+val JSON_PLAIN: Json = Json { prettyPrint = false; useArrayPolymorphism = true }
+
 class MetaSerializerTest {
     val meta = Meta {
         "a" put 22
@@ -19,29 +26,33 @@ class MetaSerializerTest {
 
     @Test
     fun testMetaSerialization() {
-        val string = JSON_PRETTY.stringify(MetaSerializer, meta)
-        val restored = JSON_PLAIN.parse(MetaSerializer, string)
-        assertEquals(restored, meta)
+        val string = JSON_PRETTY.encodeToString(MetaSerializer, meta)
+        println(string)
+        val restored = JSON_PLAIN.decodeFromString(MetaSerializer, string)
+        assertEquals(meta, restored)
     }
 
+    @OptIn(ExperimentalSerializationApi::class)
     @Test
     fun testCborSerialization() {
-        val bytes = Cbor.dump(MetaSerializer, meta)
-        println(bytes.contentToString())
-        val restored = Cbor.load(MetaSerializer, bytes)
-        assertEquals(restored, meta)
+        val bytes = Cbor.encodeToByteArray(MetaSerializer, meta)
+        println(bytes.decodeToString())
+        val restored = Cbor.decodeFromByteArray(MetaSerializer, bytes)
+        assertEquals(meta, restored)
     }
 
     @Test
     fun testNameSerialization() {
         val name = "a.b.c".toName()
-        val string = JSON_PRETTY.stringify(Name.serializer(), name)
-        val restored = JSON_PLAIN.parse(Name.serializer(), string)
-        assertEquals(restored, name)
+        val string = JSON_PRETTY.encodeToString(Name.serializer(), name)
+        val restored = JSON_PLAIN.decodeFromString(Name.serializer(), string)
+        assertEquals(name, restored)
     }
 
+    @OptIn(ExperimentalSerializationApi::class)
     @Test
     fun testMetaItemDescriptor() {
         val descriptor = MetaItem.serializer(MetaSerializer).descriptor.getElementDescriptor(0)
+        println(descriptor)
     }
 }
\ No newline at end of file
diff --git a/dataforge-io/src/commonTest/kotlin/hep/dataforge/io/ioTestUtils.kt b/dataforge-io/src/commonTest/kotlin/hep/dataforge/io/ioTestUtils.kt
index 2694ff8f..55831f03 100644
--- a/dataforge-io/src/commonTest/kotlin/hep/dataforge/io/ioTestUtils.kt
+++ b/dataforge-io/src/commonTest/kotlin/hep/dataforge/io/ioTestUtils.kt
@@ -3,5 +3,5 @@ package hep.dataforge.io
 import kotlinx.io.ByteArrayInput
 import kotlinx.io.use
 
-fun <T : Any> IOFormat<T>.toByteArray(obj: T): ByteArray = buildByteArray { writeObject(obj) }
-fun <T : Any> IOFormat<T>.readByteArray(array: ByteArray): T = ByteArrayInput(array).use { it.readObject() }
\ No newline at end of file
+fun <T : Any> IOFormat<T>.writeToByteArray(obj: T): ByteArray = buildByteArray { writeObject(this, obj) }
+fun <T : Any> IOFormat<T>.readFromByteArray(array: ByteArray): T = ByteArrayInput(array).use { readObject(it) }
\ No newline at end of file
diff --git a/dataforge-io/src/jvmMain/kotlin/hep/dataforge/io/fileIO.kt b/dataforge-io/src/jvmMain/kotlin/hep/dataforge/io/fileIO.kt
index 044cf932..0e53ed89 100644
--- a/dataforge-io/src/jvmMain/kotlin/hep/dataforge/io/fileIO.kt
+++ b/dataforge-io/src/jvmMain/kotlin/hep/dataforge/io/fileIO.kt
@@ -11,12 +11,12 @@ import java.nio.file.StandardOpenOption
 import kotlin.reflect.full.isSuperclassOf
 import kotlin.streams.asSequence
 
-fun <R> Path.read(block: Input.() -> R): R = asBinary().read(block = block)
+public fun <R> Path.read(block: Input.() -> R): R = asBinary().read(block = block)
 
 /**
  * Write a live output to a newly created file. If file does not exist, throws error
  */
-fun Path.write(block: Output.() -> Unit): Unit {
+public fun Path.write(block: Output.() -> Unit): Unit {
     val stream = Files.newOutputStream(this, StandardOpenOption.WRITE, StandardOpenOption.CREATE_NEW)
     stream.asOutput().use(block)
 }
@@ -24,7 +24,7 @@ fun Path.write(block: Output.() -> Unit): Unit {
 /**
  * Create a new file or append to exiting one with given output [block]
  */
-fun Path.append(block: Output.() -> Unit): Unit {
+public fun Path.append(block: Output.() -> Unit): Unit {
     val stream = Files.newOutputStream(
         this,
         StandardOpenOption.WRITE, StandardOpenOption.APPEND, StandardOpenOption.CREATE
@@ -35,7 +35,7 @@ fun Path.append(block: Output.() -> Unit): Unit {
 /**
  * Create a new file or replace existing one using given output [block]
  */
-fun Path.rewrite(block: Output.() -> Unit): Unit {
+public fun Path.rewrite(block: Output.() -> Unit): Unit {
     val stream = Files.newOutputStream(
         this,
         StandardOpenOption.WRITE, StandardOpenOption.TRUNCATE_EXISTING, StandardOpenOption.CREATE
@@ -43,9 +43,9 @@ fun Path.rewrite(block: Output.() -> Unit): Unit {
     stream.asOutput().use(block)
 }
 
-fun Path.readEnvelope(format: EnvelopeFormat): Envelope {
+public fun Path.readEnvelope(format: EnvelopeFormat): Envelope {
     val partialEnvelope: PartialEnvelope = asBinary().read {
-        format.run { readPartial() }
+        format.run { readPartial(this@read) }
     }
     val offset: Int = partialEnvelope.dataOffset.toInt()
     val size: Int = partialEnvelope.dataSize?.toInt() ?: (Files.size(this).toInt() - offset)
@@ -58,7 +58,7 @@ fun Path.readEnvelope(format: EnvelopeFormat): Envelope {
  */
 @Suppress("UNCHECKED_CAST")
 @DFExperimental
-inline fun <reified T : Any> IOPlugin.resolveIOFormat(): IOFormat<T>? {
+public inline fun <reified T : Any> IOPlugin.resolveIOFormat(): IOFormat<T>? {
     return ioFormatFactories.find { it.type.isSuperclassOf(T::class) } as IOFormat<T>?
 }
 
@@ -66,7 +66,11 @@ inline fun <reified T : Any> IOPlugin.resolveIOFormat(): IOFormat<T>? {
  * Read file containing meta using given [formatOverride] or file extension to infer meta type.
  * If [path] is a directory search for file starting with `meta` in it
  */
-fun IOPlugin.readMetaFile(path: Path, formatOverride: MetaFormat? = null, descriptor: NodeDescriptor? = null): Meta {
+public fun IOPlugin.readMetaFile(
+    path: Path,
+    formatOverride: MetaFormat? = null,
+    descriptor: NodeDescriptor? = null,
+): Meta {
     if (!Files.exists(path)) error("Meta file $path does not exist")
 
     val actualPath: Path = if (Files.isDirectory(path)) {
@@ -80,7 +84,7 @@ fun IOPlugin.readMetaFile(path: Path, formatOverride: MetaFormat? = null, descri
     val metaFormat = formatOverride ?: resolveMetaFormat(extension) ?: error("Can't resolve meta format $extension")
     return metaFormat.run {
         actualPath.read {
-            readMeta(descriptor)
+            readMeta(this, descriptor)
         }
     }
 }
@@ -89,11 +93,11 @@ fun IOPlugin.readMetaFile(path: Path, formatOverride: MetaFormat? = null, descri
  * Write meta to file using [metaFormat]. If [path] is a directory, write a file with name equals name of [metaFormat].
  * Like "meta.json"
  */
-fun IOPlugin.writeMetaFile(
+public fun IOPlugin.writeMetaFile(
     path: Path,
     meta: Meta,
     metaFormat: MetaFormatFactory = JsonMetaFormat,
-    descriptor: NodeDescriptor? = null
+    descriptor: NodeDescriptor? = null,
 ) {
     val actualPath = if (Files.isDirectory(path)) {
         path.resolve("@" + metaFormat.name.toString())
@@ -102,7 +106,7 @@ fun IOPlugin.writeMetaFile(
     }
     metaFormat.run {
         actualPath.write {
-            writeMeta(meta, descriptor)
+            writeMeta(this, meta, descriptor)
         }
     }
 }
@@ -111,7 +115,7 @@ fun IOPlugin.writeMetaFile(
  * Return inferred [EnvelopeFormat] if only one format could read given file. If no format accepts file, return null. If
  * multiple formats accepts file, throw an error.
  */
-fun IOPlugin.peekBinaryFormat(path: Path): EnvelopeFormat? {
+public fun IOPlugin.peekBinaryFormat(path: Path): EnvelopeFormat? {
     val binary = path.asBinary()
     val formats = envelopeFormatFactories.mapNotNull { factory ->
         binary.read {
@@ -126,8 +130,8 @@ fun IOPlugin.peekBinaryFormat(path: Path): EnvelopeFormat? {
     }
 }
 
-val IOPlugin.Companion.META_FILE_NAME: String get() = "@meta"
-val IOPlugin.Companion.DATA_FILE_NAME: String get() = "@data"
+public val IOPlugin.Companion.META_FILE_NAME: String get() = "@meta"
+public val IOPlugin.Companion.DATA_FILE_NAME: String get() = "@data"
 
 /**
  * Read and envelope from file if the file exists, return null if file does not exist.
@@ -143,17 +147,18 @@ val IOPlugin.Companion.DATA_FILE_NAME: String get() = "@data"
  * Return null otherwise.
  */
 @DFExperimental
-fun IOPlugin.readEnvelopeFile(
+public fun IOPlugin.readEnvelopeFile(
     path: Path,
     readNonEnvelopes: Boolean = false,
-    formatPeeker: IOPlugin.(Path) -> EnvelopeFormat? = IOPlugin::peekBinaryFormat
+    formatPeeker: IOPlugin.(Path) -> EnvelopeFormat? = IOPlugin::peekBinaryFormat,
 ): Envelope? {
     if (!Files.exists(path)) return null
 
     //read two-files directory
     if (Files.isDirectory(path)) {
-        val metaFile = Files.list(path).asSequence()
-            .singleOrNull { it.fileName.toString().startsWith(IOPlugin.META_FILE_NAME) }
+        val metaFile = Files.list(path).asSequence().singleOrNull {
+            it.fileName.toString().startsWith(IOPlugin.META_FILE_NAME)
+        }
 
         val meta = if (metaFile == null) {
             Meta.EMPTY
@@ -182,9 +187,9 @@ fun IOPlugin.readEnvelopeFile(
 /**
  * Write a binary into file. Throws an error if file already exists
  */
-fun <T : Any> IOFormat<T>.writeToFile(path: Path, obj: T) {
+public fun <T : Any> IOFormat<T>.writeToFile(path: Path, obj: T) {
     path.write {
-        writeObject(obj)
+        writeObject(this, obj)
     }
 }
 
@@ -192,16 +197,14 @@ fun <T : Any> IOFormat<T>.writeToFile(path: Path, obj: T) {
  * Write envelope file to given [path] using [envelopeFormat] and optional [metaFormat]
  */
 @DFExperimental
-fun IOPlugin.writeEnvelopeFile(
+public fun IOPlugin.writeEnvelopeFile(
     path: Path,
     envelope: Envelope,
     envelopeFormat: EnvelopeFormat = TaggedEnvelopeFormat,
-    metaFormat: MetaFormatFactory? = null
+    metaFormat: MetaFormatFactory? = null,
 ) {
     path.rewrite {
-        with(envelopeFormat) {
-            writeEnvelope(envelope, metaFormat ?: envelopeFormat.defaultMetaFormat)
-        }
+        envelopeFormat.writeEnvelope(this, envelope, metaFormat ?: envelopeFormat.defaultMetaFormat)
     }
 }
 
@@ -209,10 +212,10 @@ fun IOPlugin.writeEnvelopeFile(
  * Write separate meta and data files to given directory [path]
  */
 @DFExperimental
-fun IOPlugin.writeEnvelopeDirectory(
+public fun IOPlugin.writeEnvelopeDirectory(
     path: Path,
     envelope: Envelope,
-    metaFormat: MetaFormatFactory = JsonMetaFormat
+    metaFormat: MetaFormatFactory = JsonMetaFormat,
 ) {
     if (!Files.exists(path)) {
         Files.createDirectories(path)
diff --git a/dataforge-io/src/jvmMain/kotlin/hep/dataforge/io/functionsJVM.kt b/dataforge-io/src/jvmMain/kotlin/hep/dataforge/io/functionsJVM.kt
deleted file mode 100644
index ccd57c55..00000000
--- a/dataforge-io/src/jvmMain/kotlin/hep/dataforge/io/functionsJVM.kt
+++ /dev/null
@@ -1,28 +0,0 @@
-package hep.dataforge.io
-
-import hep.dataforge.io.functions.FunctionServer
-import hep.dataforge.io.functions.function
-import hep.dataforge.meta.Meta
-import hep.dataforge.names.Name
-import kotlin.reflect.KClass
-import kotlin.reflect.full.isSuperclassOf
-
-
-fun IOPlugin.resolveIOFormatName(type: KClass<*>): Name {
-    return ioFormatFactories.find { it.type.isSuperclassOf(type) }?.name
-        ?: error("Can't resolve IOFormat for type $type")
-}
-
-inline fun <reified T : Any, reified R : Any> IOPlugin.generateFunctionMeta(functionName: String): Meta = Meta {
-    FunctionServer.FUNCTION_NAME_KEY put functionName
-    FunctionServer.INPUT_FORMAT_KEY put resolveIOFormatName(T::class).toString()
-    FunctionServer.OUTPUT_FORMAT_KEY put resolveIOFormatName(R::class).toString()
-}
-
-inline fun <reified T : Any, reified R : Any> FunctionServer.function(
-    functionName: String
-): (suspend (T) -> R) {
-    val plugin = context.plugins.get<IOPlugin>() ?: error("IO plugin not loaded")
-    val meta = plugin.generateFunctionMeta<T, R>(functionName)
-    return function(meta)
-}
\ No newline at end of file
diff --git a/dataforge-io/src/jvmMain/kotlin/hep/dataforge/io/tcp/streams.kt b/dataforge-io/src/jvmMain/kotlin/hep/dataforge/io/streamsIO.kt
similarity index 75%
rename from dataforge-io/src/jvmMain/kotlin/hep/dataforge/io/tcp/streams.kt
rename to dataforge-io/src/jvmMain/kotlin/hep/dataforge/io/streamsIO.kt
index ec79eb22..ff392552 100644
--- a/dataforge-io/src/jvmMain/kotlin/hep/dataforge/io/tcp/streams.kt
+++ b/dataforge-io/src/jvmMain/kotlin/hep/dataforge/io/streamsIO.kt
@@ -1,4 +1,4 @@
-package hep.dataforge.io.tcp
+package hep.dataforge.io
 
 import kotlinx.io.*
 import kotlinx.io.buffer.Buffer
@@ -30,16 +30,16 @@ private class BlockingStreamInput(val source: InputStream) : Input() {
     }
 }
 
-fun <R> InputStream.read(size: Int, block: Input.() -> R): R {
+public fun <R> InputStream.read(size: Int, block: Input.() -> R): R {
     val buffer = ByteArray(size)
     read(buffer)
     return buffer.asBinary().read(block = block)
 }
 
-fun <R> InputStream.read(block: Input.() -> R): R = asInput().block()
+public fun <R> InputStream.read(block: Input.() -> R): R = asInput().block()
 
-fun <R> InputStream.readBlocking(block: Input.() -> R): R = BlockingStreamInput(this).block()
+public fun <R> InputStream.readBlocking(block: Input.() -> R): R = BlockingStreamInput(this).block()
 
-inline fun OutputStream.write(block: Output.() -> Unit) {
+public inline fun OutputStream.write(block: Output.() -> Unit) {
     asOutput().block()
 }
\ No newline at end of file
diff --git a/dataforge-io/src/jvmMain/kotlin/hep/dataforge/io/tcp/EnvelopeClient.kt b/dataforge-io/src/jvmMain/kotlin/hep/dataforge/io/tcp/EnvelopeClient.kt
deleted file mode 100644
index 156acd89..00000000
--- a/dataforge-io/src/jvmMain/kotlin/hep/dataforge/io/tcp/EnvelopeClient.kt
+++ /dev/null
@@ -1,65 +0,0 @@
-package hep.dataforge.io.tcp
-
-import hep.dataforge.context.Context
-import hep.dataforge.context.ContextAware
-import hep.dataforge.io.*
-import hep.dataforge.meta.Meta
-import kotlinx.coroutines.asCoroutineDispatcher
-import kotlinx.coroutines.withContext
-import java.net.Socket
-import java.util.concurrent.Executors
-import kotlin.time.ExperimentalTime
-
-@ExperimentalTime
-class EnvelopeClient(
-    override val context: Context,
-    val host: String,
-    val port: Int,
-    formatFactory: EnvelopeFormatFactory = TaggedEnvelopeFormat,
-    formatMeta: Meta = Meta.EMPTY
-) : Responder, ContextAware {
-
-    private val dispatcher = Executors.newSingleThreadExecutor().asCoroutineDispatcher()
-
-    private val format = formatFactory(formatMeta, context = context)
-
-//    private var socket: SocketChannel? = null
-//
-//    private fun getSocket(): Socket {
-//        val socket = socket ?: Socket(host, port).also { this.socket = it }
-//        return if (socket.isConnected) {
-//            socket
-//        } else {
-//            Socket(host, port).also { this.socket = it }
-//        }
-//    }
-
-    suspend fun close() {
-        try {
-            respond(
-                Envelope {
-                    type = EnvelopeServer.SHUTDOWN_ENVELOPE_TYPE
-                }
-            )
-        } catch (ex: Exception) {
-            logger.error { ex }
-        }
-    }
-
-
-    override suspend fun respond(request: Envelope): Envelope = withContext(dispatcher) {
-        //val address = InetSocketAddress(host,port)
-        val socket = Socket(host, port)
-        val inputStream = socket.getInputStream()
-        val outputStream = socket.getOutputStream()
-        format.run {
-            outputStream.write {
-                writeObject(request)
-            }
-            logger.debug { "Sent request with type ${request.type} to ${socket.remoteSocketAddress}" }
-            val res = inputStream.readBlocking { readObject() }
-            logger.debug { "Received response with type ${res.type} from ${socket.remoteSocketAddress}" }
-            return@withContext res
-        }
-    }
-}
\ No newline at end of file
diff --git a/dataforge-io/src/jvmMain/kotlin/hep/dataforge/io/tcp/EnvelopeServer.kt b/dataforge-io/src/jvmMain/kotlin/hep/dataforge/io/tcp/EnvelopeServer.kt
deleted file mode 100644
index b9569279..00000000
--- a/dataforge-io/src/jvmMain/kotlin/hep/dataforge/io/tcp/EnvelopeServer.kt
+++ /dev/null
@@ -1,103 +0,0 @@
-package hep.dataforge.io.tcp
-
-import hep.dataforge.context.Context
-import hep.dataforge.context.ContextAware
-import hep.dataforge.io.EnvelopeFormatFactory
-import hep.dataforge.io.Responder
-import hep.dataforge.io.TaggedEnvelopeFormat
-import hep.dataforge.io.type
-import hep.dataforge.meta.Meta
-import kotlinx.coroutines.*
-import java.net.ServerSocket
-import java.net.Socket
-import kotlin.concurrent.thread
-
-class EnvelopeServer(
-    override val context: Context,
-    val port: Int,
-    val responder: Responder,
-    val scope: CoroutineScope,
-    formatFactory: EnvelopeFormatFactory = TaggedEnvelopeFormat,
-    formatMeta: Meta = Meta.EMPTY
-) : ContextAware {
-
-    private var job: Job? = null
-
-    private val format = formatFactory(formatMeta, context = context)
-
-    fun start() {
-        if (job == null) {
-            logger.info { "Starting envelope server on port $port" }
-            job = scope.launch(Dispatchers.IO) {
-                val serverSocket = ServerSocket(port)
-                //TODO add handshake and format negotiation
-                while (isActive && !serverSocket.isClosed) {
-                    val socket = serverSocket.accept()
-                    logger.info { "Accepted connection from ${socket.remoteSocketAddress}" }
-                    readSocket(socket)
-                }
-            }
-        }
-    }
-
-    fun stop() {
-        logger.info { "Stopping envelope server on port $port" }
-        job?.cancel()
-        job = null
-    }
-
-//    private fun CoroutineScope.readSocket(socket: Socket) {
-//        launch(Dispatchers.IO) {
-//            val input = socket.getInputStream().asInput()
-//            val output = socket.getOutputStream().asOutput()
-//            format.run {
-//                while (isActive && socket.isConnected) {
-//                    val request = input.readThis()
-//                    logger.debug { "Accepted request with type ${request.type} from ${socket.remoteSocketAddress}" }
-//                    if (request.type == SHUTDOWN_ENVELOPE_TYPE) {
-//                        //Echo shutdown command
-//                        logger.info { "Accepted graceful shutdown signal from ${socket.inetAddress}" }
-//                        socket.close()
-//                        cancel("Graceful connection shutdown requested by client")
-//                    }
-//                    val response = responder.respond(request)
-//                    output.writeThis(response)
-//                }
-//            }
-//        }
-//    }
-
-    private fun readSocket(socket: Socket) {
-        thread {
-            val inputStream = socket.getInputStream()
-            val outputStream = socket.getOutputStream()
-            format.run {
-                while (socket.isConnected) {
-                    val request = inputStream.readBlocking { readObject() }
-                    logger.debug { "Accepted request with type ${request.type} from ${socket.remoteSocketAddress}" }
-                    if (request.type == SHUTDOWN_ENVELOPE_TYPE) {
-                        //Echo shutdown command
-                        outputStream.write {
-                            writeObject(request)
-                        }
-                        logger.info { "Accepted graceful shutdown signal from ${socket.inetAddress}" }
-                        socket.close()
-                        return@thread
-//                        cancel("Graceful connection shutdown requested by client")
-                    }
-                    runBlocking {
-                        val response = responder.respond(request)
-                        outputStream.write {
-                            writeObject(response)
-                        }
-                        logger.debug { "Sent response with type ${response.type} to ${socket.remoteSocketAddress}" }
-                    }
-                }
-            }
-        }
-    }
-
-    companion object {
-        const val SHUTDOWN_ENVELOPE_TYPE = "@shutdown"
-    }
-}
\ No newline at end of file
diff --git a/dataforge-io/src/jvmTest/kotlin/hep/dataforge/io/tcp/EnvelopeServerTest.kt b/dataforge-io/src/jvmTest/kotlin/hep/dataforge/io/tcp/EnvelopeServerTest.kt
deleted file mode 100644
index 48c108d4..00000000
--- a/dataforge-io/src/jvmTest/kotlin/hep/dataforge/io/tcp/EnvelopeServerTest.kt
+++ /dev/null
@@ -1,70 +0,0 @@
-package hep.dataforge.io.tcp
-
-import hep.dataforge.context.Global
-import hep.dataforge.io.Envelope
-import hep.dataforge.io.Responder
-import hep.dataforge.io.TaggedEnvelopeFormat
-import hep.dataforge.io.toByteArray
-import kotlinx.coroutines.GlobalScope
-import kotlinx.coroutines.runBlocking
-import kotlinx.io.writeDouble
-import org.junit.jupiter.api.AfterAll
-import org.junit.jupiter.api.BeforeAll
-import org.junit.jupiter.api.Timeout
-import kotlin.test.Test
-import kotlin.test.assertEquals
-import kotlin.time.ExperimentalTime
-
-@ExperimentalStdlibApi
-object EchoResponder : Responder {
-    override suspend fun respond(request: Envelope): Envelope {
-        val string = TaggedEnvelopeFormat().run { toByteArray(request).decodeToString() }
-        println("ECHO:")
-        println(string)
-        return request
-    }
-}
-
-@ExperimentalTime
-@ExperimentalStdlibApi
-class EnvelopeServerTest {
-    companion object {
-        @JvmStatic
-        val echoEnvelopeServer = EnvelopeServer(Global, 7778, EchoResponder, GlobalScope)
-
-        @BeforeAll
-        @JvmStatic
-        fun start() {
-            echoEnvelopeServer.start()
-        }
-
-        @AfterAll
-        @JvmStatic
-        fun close() {
-            echoEnvelopeServer.stop()
-        }
-    }
-
-    @Test
-    @Timeout(1)
-    fun doEchoTest() {
-        val request = Envelope {
-            type = "test.echo"
-            meta {
-                "test.value" put 22
-            }
-            data {
-                writeDouble(22.7)
-            }
-        }
-        val client = EnvelopeClient(Global, host = "localhost", port = 7778)
-        runBlocking {
-            val response = client.respond(request)
-
-
-            assertEquals(request.meta, response.meta)
-//            assertEquals(request.data?.toBytes()?.decodeToString(), response.data?.toBytes()?.decodeToString())
-            client.close()
-        }
-    }
-}
\ No newline at end of file
diff --git a/dataforge-meta/api/dataforge-meta.api b/dataforge-meta/api/dataforge-meta.api
new file mode 100644
index 00000000..f4b8d3ed
--- /dev/null
+++ b/dataforge-meta/api/dataforge-meta.api
@@ -0,0 +1,1015 @@
+public abstract class hep/dataforge/meta/AbstractMetaNode : hep/dataforge/meta/MetaBase, hep/dataforge/meta/MetaNode {
+	public fun <init> ()V
+	public fun getItem (Lhep/dataforge/names/Name;)Lhep/dataforge/meta/MetaItem;
+	public fun toMeta ()Lhep/dataforge/meta/Meta;
+}
+
+public abstract class hep/dataforge/meta/AbstractMutableMeta : hep/dataforge/meta/AbstractMetaNode, hep/dataforge/meta/MutableMeta {
+	public fun <init> ()V
+	protected final fun getChildren ()Ljava/util/Map;
+	public fun getItems ()Ljava/util/Map;
+	protected fun replaceItem (Lhep/dataforge/names/NameToken;Lhep/dataforge/meta/MetaItem;Lhep/dataforge/meta/MetaItem;)V
+	public fun setItem (Lhep/dataforge/names/Name;Lhep/dataforge/meta/MetaItem;)V
+	protected final fun wrapItem (Lhep/dataforge/meta/MetaItem;)Lhep/dataforge/meta/MetaItem;
+	protected abstract fun wrapNode (Lhep/dataforge/meta/Meta;)Lhep/dataforge/meta/MutableMeta;
+}
+
+public final class hep/dataforge/meta/Config : hep/dataforge/meta/AbstractMutableMeta, hep/dataforge/meta/ObservableMeta {
+	public static final field ConfigSerializer Lhep/dataforge/meta/Config$ConfigSerializer;
+	public fun <init> ()V
+	public synthetic fun empty$dataforge_meta ()Lhep/dataforge/meta/MutableMeta;
+	public fun onChange (Ljava/lang/Object;Lkotlin/jvm/functions/Function3;)V
+	public fun removeListener (Ljava/lang/Object;)V
+	public synthetic fun wrapNode (Lhep/dataforge/meta/Meta;)Lhep/dataforge/meta/MutableMeta;
+}
+
+public final class hep/dataforge/meta/Config$ConfigSerializer : kotlinx/serialization/KSerializer {
+	public fun deserialize (Lkotlinx/serialization/encoding/Decoder;)Lhep/dataforge/meta/Config;
+	public synthetic fun deserialize (Lkotlinx/serialization/encoding/Decoder;)Ljava/lang/Object;
+	public final fun empty ()Lhep/dataforge/meta/Config;
+	public fun getDescriptor ()Lkotlinx/serialization/descriptors/SerialDescriptor;
+	public fun serialize (Lkotlinx/serialization/encoding/Encoder;Lhep/dataforge/meta/Config;)V
+	public synthetic fun serialize (Lkotlinx/serialization/encoding/Encoder;Ljava/lang/Object;)V
+	public final fun serializer ()Lkotlinx/serialization/KSerializer;
+}
+
+public final class hep/dataforge/meta/ConfigKt {
+	public static final fun asConfig (Lhep/dataforge/meta/Meta;)Lhep/dataforge/meta/Config;
+	public static final fun get (Lhep/dataforge/meta/Config;Lhep/dataforge/names/NameToken;)Lhep/dataforge/meta/MetaItem;
+}
+
+public abstract interface class hep/dataforge/meta/Configurable {
+	public abstract fun getConfig ()Lhep/dataforge/meta/Config;
+}
+
+public final class hep/dataforge/meta/ConfigurableKt {
+	public static final fun config (Lhep/dataforge/meta/Configurable;Lhep/dataforge/names/Name;)Lkotlin/properties/ReadWriteProperty;
+	public static synthetic fun config$default (Lhep/dataforge/meta/Configurable;Lhep/dataforge/names/Name;ILjava/lang/Object;)Lkotlin/properties/ReadWriteProperty;
+	public static final fun configure (Lhep/dataforge/meta/Configurable;Lhep/dataforge/meta/Meta;)Lhep/dataforge/meta/Configurable;
+	public static final fun configure (Lhep/dataforge/meta/Configurable;Lkotlin/jvm/functions/Function1;)Lhep/dataforge/meta/Configurable;
+}
+
+public abstract interface annotation class hep/dataforge/meta/DFBuilder : java/lang/annotation/Annotation {
+}
+
+public abstract interface annotation class hep/dataforge/meta/DFExperimental : java/lang/annotation/Annotation {
+}
+
+public final class hep/dataforge/meta/GetIndexedKt {
+	public static final fun getIndexed (Lhep/dataforge/meta/Meta;Lhep/dataforge/names/Name;)Ljava/util/Map;
+	public static final fun getIndexed (Lhep/dataforge/meta/Meta;Ljava/lang/String;)Ljava/util/Map;
+	public static final fun getIndexed (Lhep/dataforge/meta/MetaNode;Lhep/dataforge/names/Name;)Ljava/util/Map;
+	public static final fun getIndexed (Lhep/dataforge/meta/MetaNode;Ljava/lang/String;)Ljava/util/Map;
+}
+
+public final class hep/dataforge/meta/ItemDelegateKt {
+	public static final fun boolean (Lhep/dataforge/meta/ItemProvider;Lhep/dataforge/names/Name;)Lkotlin/properties/ReadOnlyProperty;
+	public static final fun boolean (Lhep/dataforge/meta/ItemProvider;Lhep/dataforge/names/Name;Lkotlin/jvm/functions/Function0;)Lkotlin/properties/ReadOnlyProperty;
+	public static final fun boolean (Lhep/dataforge/meta/ItemProvider;ZLhep/dataforge/names/Name;)Lkotlin/properties/ReadOnlyProperty;
+	public static synthetic fun boolean$default (Lhep/dataforge/meta/ItemProvider;Lhep/dataforge/names/Name;ILjava/lang/Object;)Lkotlin/properties/ReadOnlyProperty;
+	public static synthetic fun boolean$default (Lhep/dataforge/meta/ItemProvider;Lhep/dataforge/names/Name;Lkotlin/jvm/functions/Function0;ILjava/lang/Object;)Lkotlin/properties/ReadOnlyProperty;
+	public static synthetic fun boolean$default (Lhep/dataforge/meta/ItemProvider;ZLhep/dataforge/names/Name;ILjava/lang/Object;)Lkotlin/properties/ReadOnlyProperty;
+	public static final fun convert (Lkotlin/properties/ReadOnlyProperty;Lhep/dataforge/meta/transformations/MetaConverter;)Lkotlin/properties/ReadOnlyProperty;
+	public static final fun convert (Lkotlin/properties/ReadOnlyProperty;Lhep/dataforge/meta/transformations/MetaConverter;Lkotlin/jvm/functions/Function0;)Lkotlin/properties/ReadOnlyProperty;
+	public static final fun convert (Lkotlin/properties/ReadOnlyProperty;Lkotlin/jvm/functions/Function1;)Lkotlin/properties/ReadOnlyProperty;
+	public static final fun double (Lhep/dataforge/meta/ItemProvider;DLhep/dataforge/names/Name;)Lkotlin/properties/ReadOnlyProperty;
+	public static final fun double (Lhep/dataforge/meta/ItemProvider;Lhep/dataforge/names/Name;)Lkotlin/properties/ReadOnlyProperty;
+	public static synthetic fun double$default (Lhep/dataforge/meta/ItemProvider;DLhep/dataforge/names/Name;ILjava/lang/Object;)Lkotlin/properties/ReadOnlyProperty;
+	public static synthetic fun double$default (Lhep/dataforge/meta/ItemProvider;Lhep/dataforge/names/Name;ILjava/lang/Object;)Lkotlin/properties/ReadOnlyProperty;
+	public static final fun float (Lhep/dataforge/meta/ItemProvider;FLhep/dataforge/names/Name;)Lkotlin/properties/ReadOnlyProperty;
+	public static final fun float (Lhep/dataforge/meta/ItemProvider;Lhep/dataforge/names/Name;)Lkotlin/properties/ReadOnlyProperty;
+	public static synthetic fun float$default (Lhep/dataforge/meta/ItemProvider;FLhep/dataforge/names/Name;ILjava/lang/Object;)Lkotlin/properties/ReadOnlyProperty;
+	public static synthetic fun float$default (Lhep/dataforge/meta/ItemProvider;Lhep/dataforge/names/Name;ILjava/lang/Object;)Lkotlin/properties/ReadOnlyProperty;
+	public static final fun int (Lhep/dataforge/meta/ItemProvider;ILhep/dataforge/names/Name;)Lkotlin/properties/ReadOnlyProperty;
+	public static final fun int (Lhep/dataforge/meta/ItemProvider;Lhep/dataforge/names/Name;)Lkotlin/properties/ReadOnlyProperty;
+	public static synthetic fun int$default (Lhep/dataforge/meta/ItemProvider;ILhep/dataforge/names/Name;ILjava/lang/Object;)Lkotlin/properties/ReadOnlyProperty;
+	public static synthetic fun int$default (Lhep/dataforge/meta/ItemProvider;Lhep/dataforge/names/Name;ILjava/lang/Object;)Lkotlin/properties/ReadOnlyProperty;
+	public static final fun item (Lhep/dataforge/meta/ItemProvider;Lhep/dataforge/names/Name;)Lkotlin/properties/ReadOnlyProperty;
+	public static synthetic fun item$default (Lhep/dataforge/meta/ItemProvider;Lhep/dataforge/names/Name;ILjava/lang/Object;)Lkotlin/properties/ReadOnlyProperty;
+	public static final fun long (Lhep/dataforge/meta/ItemProvider;JLhep/dataforge/names/Name;)Lkotlin/properties/ReadOnlyProperty;
+	public static final fun long (Lhep/dataforge/meta/ItemProvider;Lhep/dataforge/names/Name;)Lkotlin/properties/ReadOnlyProperty;
+	public static synthetic fun long$default (Lhep/dataforge/meta/ItemProvider;JLhep/dataforge/names/Name;ILjava/lang/Object;)Lkotlin/properties/ReadOnlyProperty;
+	public static synthetic fun long$default (Lhep/dataforge/meta/ItemProvider;Lhep/dataforge/names/Name;ILjava/lang/Object;)Lkotlin/properties/ReadOnlyProperty;
+	public static final fun node (Lhep/dataforge/meta/ItemProvider;Lhep/dataforge/names/Name;)Lkotlin/properties/ReadOnlyProperty;
+	public static synthetic fun node$default (Lhep/dataforge/meta/ItemProvider;Lhep/dataforge/names/Name;ILjava/lang/Object;)Lkotlin/properties/ReadOnlyProperty;
+	public static final fun number (Lhep/dataforge/meta/ItemProvider;Lhep/dataforge/names/Name;)Lkotlin/properties/ReadOnlyProperty;
+	public static final fun number (Lhep/dataforge/meta/ItemProvider;Lhep/dataforge/names/Name;Lkotlin/jvm/functions/Function0;)Lkotlin/properties/ReadOnlyProperty;
+	public static final fun number (Lhep/dataforge/meta/ItemProvider;Ljava/lang/Number;Lhep/dataforge/names/Name;)Lkotlin/properties/ReadOnlyProperty;
+	public static synthetic fun number$default (Lhep/dataforge/meta/ItemProvider;Lhep/dataforge/names/Name;ILjava/lang/Object;)Lkotlin/properties/ReadOnlyProperty;
+	public static synthetic fun number$default (Lhep/dataforge/meta/ItemProvider;Lhep/dataforge/names/Name;Lkotlin/jvm/functions/Function0;ILjava/lang/Object;)Lkotlin/properties/ReadOnlyProperty;
+	public static synthetic fun number$default (Lhep/dataforge/meta/ItemProvider;Ljava/lang/Number;Lhep/dataforge/names/Name;ILjava/lang/Object;)Lkotlin/properties/ReadOnlyProperty;
+	public static final fun string (Lhep/dataforge/meta/ItemProvider;Lhep/dataforge/names/Name;)Lkotlin/properties/ReadOnlyProperty;
+	public static final fun string (Lhep/dataforge/meta/ItemProvider;Lhep/dataforge/names/Name;Lkotlin/jvm/functions/Function0;)Lkotlin/properties/ReadOnlyProperty;
+	public static final fun string (Lhep/dataforge/meta/ItemProvider;Ljava/lang/String;Lhep/dataforge/names/Name;)Lkotlin/properties/ReadOnlyProperty;
+	public static synthetic fun string$default (Lhep/dataforge/meta/ItemProvider;Lhep/dataforge/names/Name;ILjava/lang/Object;)Lkotlin/properties/ReadOnlyProperty;
+	public static synthetic fun string$default (Lhep/dataforge/meta/ItemProvider;Lhep/dataforge/names/Name;Lkotlin/jvm/functions/Function0;ILjava/lang/Object;)Lkotlin/properties/ReadOnlyProperty;
+	public static synthetic fun string$default (Lhep/dataforge/meta/ItemProvider;Ljava/lang/String;Lhep/dataforge/names/Name;ILjava/lang/Object;)Lkotlin/properties/ReadOnlyProperty;
+	public static final fun value (Lhep/dataforge/meta/ItemProvider;Lhep/dataforge/names/Name;)Lkotlin/properties/ReadOnlyProperty;
+	public static synthetic fun value$default (Lhep/dataforge/meta/ItemProvider;Lhep/dataforge/names/Name;ILjava/lang/Object;)Lkotlin/properties/ReadOnlyProperty;
+}
+
+public abstract interface class hep/dataforge/meta/ItemProvider {
+	public static final field Companion Lhep/dataforge/meta/ItemProvider$Companion;
+	public abstract fun getItem (Lhep/dataforge/names/Name;)Lhep/dataforge/meta/MetaItem;
+}
+
+public final class hep/dataforge/meta/ItemProvider$Companion {
+	public final fun getEMPTY ()Lhep/dataforge/meta/ItemProvider;
+}
+
+public final class hep/dataforge/meta/JsonMeta : hep/dataforge/meta/MetaBase {
+	public static final field Companion Lhep/dataforge/meta/JsonMeta$Companion;
+	public static final field JSON_ARRAY_KEY Ljava/lang/String;
+	public fun <init> (Lkotlinx/serialization/json/JsonObject;Lhep/dataforge/meta/descriptors/NodeDescriptor;)V
+	public synthetic fun <init> (Lkotlinx/serialization/json/JsonObject;Lhep/dataforge/meta/descriptors/NodeDescriptor;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
+	public fun getItems ()Ljava/util/Map;
+}
+
+public final class hep/dataforge/meta/JsonMeta$Companion {
+}
+
+public final class hep/dataforge/meta/JsonMetaKt {
+	public static final fun toJson (Lhep/dataforge/meta/Meta;Lhep/dataforge/meta/descriptors/NodeDescriptor;)Lkotlinx/serialization/json/JsonObject;
+	public static final fun toJson (Lhep/dataforge/values/Value;Lhep/dataforge/meta/descriptors/ValueDescriptor;)Lkotlinx/serialization/json/JsonElement;
+	public static synthetic fun toJson$default (Lhep/dataforge/meta/Meta;Lhep/dataforge/meta/descriptors/NodeDescriptor;ILjava/lang/Object;)Lkotlinx/serialization/json/JsonObject;
+	public static synthetic fun toJson$default (Lhep/dataforge/values/Value;Lhep/dataforge/meta/descriptors/ValueDescriptor;ILjava/lang/Object;)Lkotlinx/serialization/json/JsonElement;
+	public static final fun toMeta (Lkotlinx/serialization/json/JsonObject;Lhep/dataforge/meta/descriptors/NodeDescriptor;)Lhep/dataforge/meta/JsonMeta;
+	public static synthetic fun toMeta$default (Lkotlinx/serialization/json/JsonObject;Lhep/dataforge/meta/descriptors/NodeDescriptor;ILjava/lang/Object;)Lhep/dataforge/meta/JsonMeta;
+	public static final fun toMetaItem (Lkotlinx/serialization/json/JsonElement;Lhep/dataforge/meta/descriptors/ItemDescriptor;)Lhep/dataforge/meta/MetaItem;
+	public static synthetic fun toMetaItem$default (Lkotlinx/serialization/json/JsonElement;Lhep/dataforge/meta/descriptors/ItemDescriptor;ILjava/lang/Object;)Lhep/dataforge/meta/MetaItem;
+	public static final fun toValue (Lkotlinx/serialization/json/JsonPrimitive;Lhep/dataforge/meta/descriptors/ValueDescriptor;)Lhep/dataforge/values/Value;
+}
+
+public final class hep/dataforge/meta/Laminate : hep/dataforge/meta/MetaBase {
+	public static final field Companion Lhep/dataforge/meta/Laminate$Companion;
+	public fun <init> (Ljava/util/List;)V
+	public fun getItems ()Ljava/util/Map;
+	public final fun getLayers ()Ljava/util/List;
+	public final fun merge ()Lhep/dataforge/meta/SealedMeta;
+}
+
+public final class hep/dataforge/meta/Laminate$Companion {
+	public final fun getMergeRule ()Lkotlin/jvm/functions/Function1;
+	public final fun getReplaceRule ()Lkotlin/jvm/functions/Function1;
+}
+
+public final class hep/dataforge/meta/LaminateKt {
+	public static final fun Laminate ([Lhep/dataforge/meta/Meta;)Lhep/dataforge/meta/Laminate;
+	public static final fun getFirst (Lhep/dataforge/meta/Laminate;Lhep/dataforge/names/Name;)Lhep/dataforge/meta/MetaItem;
+	public static final fun withBottom (Lhep/dataforge/meta/Laminate;Lhep/dataforge/meta/Meta;)Lhep/dataforge/meta/Laminate;
+	public static final fun withTop (Lhep/dataforge/meta/Laminate;Lhep/dataforge/meta/Meta;)Lhep/dataforge/meta/Laminate;
+}
+
+public final class hep/dataforge/meta/MapMetaKt {
+	public static final fun toMap (Lhep/dataforge/meta/Meta;Lhep/dataforge/meta/descriptors/NodeDescriptor;)Ljava/util/Map;
+	public static synthetic fun toMap$default (Lhep/dataforge/meta/Meta;Lhep/dataforge/meta/descriptors/NodeDescriptor;ILjava/lang/Object;)Ljava/util/Map;
+	public static final fun toMeta (Ljava/util/Map;Lhep/dataforge/meta/descriptors/NodeDescriptor;)Lhep/dataforge/meta/Meta;
+	public static synthetic fun toMeta$default (Ljava/util/Map;Lhep/dataforge/meta/descriptors/NodeDescriptor;ILjava/lang/Object;)Lhep/dataforge/meta/Meta;
+}
+
+public abstract interface class hep/dataforge/meta/Meta : hep/dataforge/meta/ItemProvider, hep/dataforge/meta/MetaRepr {
+	public static final field Companion Lhep/dataforge/meta/Meta$Companion;
+	public static final field TYPE Ljava/lang/String;
+	public static final field VALUE_KEY Ljava/lang/String;
+	public abstract fun equals (Ljava/lang/Object;)Z
+	public abstract fun getItem (Lhep/dataforge/names/Name;)Lhep/dataforge/meta/MetaItem;
+	public abstract fun getItems ()Ljava/util/Map;
+	public abstract fun hashCode ()I
+	public abstract fun toMeta ()Lhep/dataforge/meta/Meta;
+	public abstract fun toString ()Ljava/lang/String;
+}
+
+public final class hep/dataforge/meta/Meta$Companion {
+	public static final field TYPE Ljava/lang/String;
+	public static final field VALUE_KEY Ljava/lang/String;
+	public final fun getEMPTY ()Lhep/dataforge/meta/Meta;
+}
+
+public final class hep/dataforge/meta/Meta$DefaultImpls {
+	public static fun getItem (Lhep/dataforge/meta/Meta;Lhep/dataforge/names/Name;)Lhep/dataforge/meta/MetaItem;
+	public static fun toMeta (Lhep/dataforge/meta/Meta;)Lhep/dataforge/meta/Meta;
+}
+
+public abstract class hep/dataforge/meta/MetaBase : hep/dataforge/meta/Meta {
+	public fun <init> ()V
+	public fun equals (Ljava/lang/Object;)Z
+	public fun getItem (Lhep/dataforge/names/Name;)Lhep/dataforge/meta/MetaItem;
+	public fun hashCode ()I
+	public fun toMeta ()Lhep/dataforge/meta/Meta;
+	public fun toString ()Ljava/lang/String;
+}
+
+public final class hep/dataforge/meta/MetaBuilder : hep/dataforge/meta/AbstractMutableMeta {
+	public fun <init> ()V
+	public synthetic fun empty$dataforge_meta ()Lhep/dataforge/meta/MutableMeta;
+	public final fun put (Lhep/dataforge/names/Name;Lhep/dataforge/meta/Meta;)V
+	public final fun put (Lhep/dataforge/names/Name;Lhep/dataforge/meta/MetaRepr;)V
+	public final fun put (Lhep/dataforge/names/Name;Lhep/dataforge/values/Value;)V
+	public final fun put (Lhep/dataforge/names/Name;Ljava/lang/Boolean;)V
+	public final fun put (Lhep/dataforge/names/Name;Ljava/lang/Enum;)V
+	public final fun put (Lhep/dataforge/names/Name;Ljava/lang/Number;)V
+	public final fun put (Lhep/dataforge/names/Name;Ljava/lang/String;)V
+	public final fun put (Lhep/dataforge/names/Name;Lkotlin/jvm/functions/Function1;)V
+	public final fun put (Ljava/lang/String;Lhep/dataforge/meta/Meta;)V
+	public final fun put (Ljava/lang/String;Lhep/dataforge/meta/MetaItem;)V
+	public final fun put (Ljava/lang/String;Lhep/dataforge/meta/MetaRepr;)V
+	public final fun put (Ljava/lang/String;Lhep/dataforge/values/Value;)V
+	public final fun put (Ljava/lang/String;Ljava/lang/Boolean;)V
+	public final fun put (Ljava/lang/String;Ljava/lang/Enum;)V
+	public final fun put (Ljava/lang/String;Ljava/lang/Number;)V
+	public final fun put (Ljava/lang/String;Ljava/lang/String;)V
+	public final fun put (Ljava/lang/String;Lkotlin/jvm/functions/Function1;)V
+	public final fun put (Ljava/lang/String;[D)V
+	public final fun putMetas (Lhep/dataforge/names/Name;Ljava/lang/Iterable;)V
+	public final fun putMetas (Ljava/lang/String;Ljava/lang/Iterable;)V
+	public final fun putNumbers (Ljava/lang/String;Ljava/lang/Iterable;)V
+	public final fun putStrings (Ljava/lang/String;Ljava/lang/Iterable;)V
+	public final fun putValues (Lhep/dataforge/names/Name;Ljava/lang/Iterable;)V
+	public final fun putValues (Ljava/lang/String;Ljava/lang/Iterable;)V
+	public synthetic fun wrapNode (Lhep/dataforge/meta/Meta;)Lhep/dataforge/meta/MutableMeta;
+}
+
+public final class hep/dataforge/meta/MetaBuilderKt {
+	public static final fun Meta (Lkotlin/jvm/functions/Function1;)Lhep/dataforge/meta/MetaBuilder;
+	public static final fun builder (Lhep/dataforge/meta/Meta;)Lhep/dataforge/meta/MetaBuilder;
+	public static final fun edit (Lhep/dataforge/meta/Meta;Lkotlin/jvm/functions/Function1;)Lhep/dataforge/meta/MetaBuilder;
+}
+
+public abstract class hep/dataforge/meta/MetaItem {
+	public static final field Companion Lhep/dataforge/meta/MetaItem$Companion;
+	public abstract fun equals (Ljava/lang/Object;)Z
+	public abstract fun hashCode ()I
+}
+
+public final class hep/dataforge/meta/MetaItem$Companion {
+	public final fun of (Ljava/lang/Object;)Lhep/dataforge/meta/MetaItem;
+	public final fun serializer (Lkotlinx/serialization/KSerializer;)Lkotlinx/serialization/KSerializer;
+}
+
+public final class hep/dataforge/meta/MetaItem$NodeItem : hep/dataforge/meta/MetaItem {
+	public static final field Companion Lhep/dataforge/meta/MetaItem$NodeItem$Companion;
+	public fun <init> (Lhep/dataforge/meta/Meta;)V
+	public fun equals (Ljava/lang/Object;)Z
+	public final fun getNode ()Lhep/dataforge/meta/Meta;
+	public fun hashCode ()I
+	public fun toString ()Ljava/lang/String;
+}
+
+public final class hep/dataforge/meta/MetaItem$NodeItem$Companion {
+	public final fun serializer (Lkotlinx/serialization/KSerializer;)Lkotlinx/serialization/KSerializer;
+}
+
+public final class hep/dataforge/meta/MetaItem$ValueItem : hep/dataforge/meta/MetaItem {
+	public static final field Companion Lhep/dataforge/meta/MetaItem$ValueItem$Companion;
+	public fun <init> (Lhep/dataforge/values/Value;)V
+	public fun equals (Ljava/lang/Object;)Z
+	public final fun getValue ()Lhep/dataforge/values/Value;
+	public fun hashCode ()I
+	public fun toString ()Ljava/lang/String;
+}
+
+public final class hep/dataforge/meta/MetaItem$ValueItem$Companion {
+	public final fun serializer ()Lkotlinx/serialization/KSerializer;
+}
+
+public final class hep/dataforge/meta/MetaItemSerializer : kotlinx/serialization/KSerializer {
+	public static final field INSTANCE Lhep/dataforge/meta/MetaItemSerializer;
+	public fun deserialize (Lkotlinx/serialization/encoding/Decoder;)Lhep/dataforge/meta/MetaItem;
+	public synthetic fun deserialize (Lkotlinx/serialization/encoding/Decoder;)Ljava/lang/Object;
+	public fun getDescriptor ()Lkotlinx/serialization/descriptors/SerialDescriptor;
+	public fun serialize (Lkotlinx/serialization/encoding/Encoder;Lhep/dataforge/meta/MetaItem;)V
+	public synthetic fun serialize (Lkotlinx/serialization/encoding/Encoder;Ljava/lang/Object;)V
+}
+
+public final class hep/dataforge/meta/MetaKt {
+	public static final fun asMetaItem (Lhep/dataforge/meta/Meta;)Lhep/dataforge/meta/MetaItem$NodeItem;
+	public static final fun asMetaItem (Lhep/dataforge/values/Value;)Lhep/dataforge/meta/MetaItem$ValueItem;
+	public static final fun get (Lhep/dataforge/meta/Meta;Lhep/dataforge/names/Name;)Lhep/dataforge/meta/MetaItem;
+	public static final fun get (Lhep/dataforge/meta/Meta;Lhep/dataforge/names/NameToken;)Lhep/dataforge/meta/MetaItem;
+	public static final fun get (Lhep/dataforge/meta/Meta;Ljava/lang/String;)Lhep/dataforge/meta/MetaItem;
+	public static final fun get (Lhep/dataforge/meta/MetaNode;Lhep/dataforge/names/Name;)Lhep/dataforge/meta/MetaItem;
+	public static final fun get (Lhep/dataforge/meta/MetaNode;Lhep/dataforge/names/NameToken;)Lhep/dataforge/meta/MetaItem;
+	public static final fun get (Lhep/dataforge/meta/MetaNode;Ljava/lang/String;)Lhep/dataforge/meta/MetaItem;
+	public static final fun getBoolean (Lhep/dataforge/meta/MetaItem;)Ljava/lang/Boolean;
+	public static final fun getDouble (Lhep/dataforge/meta/MetaItem;)Ljava/lang/Double;
+	public static final fun getFloat (Lhep/dataforge/meta/MetaItem;)Ljava/lang/Float;
+	public static final fun getInt (Lhep/dataforge/meta/MetaItem;)Ljava/lang/Integer;
+	public static final fun getLong (Lhep/dataforge/meta/MetaItem;)Ljava/lang/Long;
+	public static final fun getNode (Lhep/dataforge/meta/MetaItem;)Lhep/dataforge/meta/Meta;
+	public static final fun getNumber (Lhep/dataforge/meta/MetaItem;)Ljava/lang/Number;
+	public static final fun getShort (Lhep/dataforge/meta/MetaItem;)Ljava/lang/Short;
+	public static final fun getString (Lhep/dataforge/meta/MetaItem;)Ljava/lang/String;
+	public static final fun getStringList (Lhep/dataforge/meta/MetaItem;)Ljava/util/List;
+	public static final fun getValue (Lhep/dataforge/meta/MetaItem;)Lhep/dataforge/values/Value;
+	public static final fun isEmpty (Lhep/dataforge/meta/Meta;)Z
+	public static final fun iterator (Lhep/dataforge/meta/Meta;)Ljava/util/Iterator;
+	public static final fun seal (Lhep/dataforge/meta/Meta;)Lhep/dataforge/meta/SealedMeta;
+	public static final fun seal (Lhep/dataforge/meta/MetaItem;)Lhep/dataforge/meta/MetaItem;
+	public static final fun sequence (Lhep/dataforge/meta/Meta;)Lkotlin/sequences/Sequence;
+	public static final fun values (Lhep/dataforge/meta/Meta;)Lkotlin/sequences/Sequence;
+}
+
+public final class hep/dataforge/meta/MetaListener {
+	public fun <init> (Ljava/lang/Object;Lkotlin/jvm/functions/Function3;)V
+	public synthetic fun <init> (Ljava/lang/Object;Lkotlin/jvm/functions/Function3;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
+	public final fun component1 ()Ljava/lang/Object;
+	public final fun component2 ()Lkotlin/jvm/functions/Function3;
+	public final fun copy (Ljava/lang/Object;Lkotlin/jvm/functions/Function3;)Lhep/dataforge/meta/MetaListener;
+	public static synthetic fun copy$default (Lhep/dataforge/meta/MetaListener;Ljava/lang/Object;Lkotlin/jvm/functions/Function3;ILjava/lang/Object;)Lhep/dataforge/meta/MetaListener;
+	public fun equals (Ljava/lang/Object;)Z
+	public final fun getAction ()Lkotlin/jvm/functions/Function3;
+	public final fun getOwner ()Ljava/lang/Object;
+	public fun hashCode ()I
+	public fun toString ()Ljava/lang/String;
+}
+
+public abstract interface class hep/dataforge/meta/MetaNode : hep/dataforge/meta/Meta {
+	public abstract fun getItems ()Ljava/util/Map;
+}
+
+public final class hep/dataforge/meta/MetaNode$DefaultImpls {
+	public static fun getItem (Lhep/dataforge/meta/MetaNode;Lhep/dataforge/names/Name;)Lhep/dataforge/meta/MetaItem;
+	public static fun toMeta (Lhep/dataforge/meta/MetaNode;)Lhep/dataforge/meta/Meta;
+}
+
+public abstract interface class hep/dataforge/meta/MetaRepr {
+	public abstract fun toMeta ()Lhep/dataforge/meta/Meta;
+}
+
+public final class hep/dataforge/meta/MetaSerializer : kotlinx/serialization/KSerializer {
+	public static final field INSTANCE Lhep/dataforge/meta/MetaSerializer;
+	public fun deserialize (Lkotlinx/serialization/encoding/Decoder;)Lhep/dataforge/meta/Meta;
+	public synthetic fun deserialize (Lkotlinx/serialization/encoding/Decoder;)Ljava/lang/Object;
+	public fun getDescriptor ()Lkotlinx/serialization/descriptors/SerialDescriptor;
+	public fun serialize (Lkotlinx/serialization/encoding/Encoder;Lhep/dataforge/meta/Meta;)V
+	public synthetic fun serialize (Lkotlinx/serialization/encoding/Encoder;Ljava/lang/Object;)V
+}
+
+public final class hep/dataforge/meta/MetaWithDefault : hep/dataforge/meta/MetaBase {
+	public fun <init> (Lhep/dataforge/meta/Meta;Lhep/dataforge/meta/ItemProvider;)V
+	public final fun getDefault ()Lhep/dataforge/meta/ItemProvider;
+	public fun getItem (Lhep/dataforge/names/Name;)Lhep/dataforge/meta/MetaItem;
+	public fun getItems ()Ljava/util/Map;
+	public final fun getMeta ()Lhep/dataforge/meta/Meta;
+}
+
+public final class hep/dataforge/meta/MetaWithDefaultKt {
+	public static final fun withDefault (Lhep/dataforge/meta/Meta;Lhep/dataforge/meta/ItemProvider;)Lhep/dataforge/meta/MetaWithDefault;
+}
+
+public final class hep/dataforge/meta/MutableItemDelegateKt {
+	public static final fun boolean (Lhep/dataforge/meta/MutableItemProvider;Lhep/dataforge/names/Name;)Lkotlin/properties/ReadWriteProperty;
+	public static final fun boolean (Lhep/dataforge/meta/MutableItemProvider;Lhep/dataforge/names/Name;Lkotlin/jvm/functions/Function0;)Lkotlin/properties/ReadWriteProperty;
+	public static final fun boolean (Lhep/dataforge/meta/MutableItemProvider;ZLhep/dataforge/names/Name;)Lkotlin/properties/ReadWriteProperty;
+	public static synthetic fun boolean$default (Lhep/dataforge/meta/MutableItemProvider;Lhep/dataforge/names/Name;ILjava/lang/Object;)Lkotlin/properties/ReadWriteProperty;
+	public static synthetic fun boolean$default (Lhep/dataforge/meta/MutableItemProvider;Lhep/dataforge/names/Name;Lkotlin/jvm/functions/Function0;ILjava/lang/Object;)Lkotlin/properties/ReadWriteProperty;
+	public static synthetic fun boolean$default (Lhep/dataforge/meta/MutableItemProvider;ZLhep/dataforge/names/Name;ILjava/lang/Object;)Lkotlin/properties/ReadWriteProperty;
+	public static final fun convert (Lkotlin/properties/ReadWriteProperty;Lhep/dataforge/meta/transformations/MetaConverter;)Lkotlin/properties/ReadWriteProperty;
+	public static final fun convert (Lkotlin/properties/ReadWriteProperty;Lhep/dataforge/meta/transformations/MetaConverter;Lkotlin/jvm/functions/Function0;)Lkotlin/properties/ReadWriteProperty;
+	public static final fun convert (Lkotlin/properties/ReadWriteProperty;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;)Lkotlin/properties/ReadWriteProperty;
+	public static final fun double (Lhep/dataforge/meta/MutableItemProvider;DLhep/dataforge/names/Name;)Lkotlin/properties/ReadWriteProperty;
+	public static final fun double (Lhep/dataforge/meta/MutableItemProvider;Lhep/dataforge/names/Name;)Lkotlin/properties/ReadWriteProperty;
+	public static synthetic fun double$default (Lhep/dataforge/meta/MutableItemProvider;DLhep/dataforge/names/Name;ILjava/lang/Object;)Lkotlin/properties/ReadWriteProperty;
+	public static synthetic fun double$default (Lhep/dataforge/meta/MutableItemProvider;Lhep/dataforge/names/Name;ILjava/lang/Object;)Lkotlin/properties/ReadWriteProperty;
+	public static final fun doubleArray (Lhep/dataforge/meta/MutableItemProvider;[DLhep/dataforge/names/Name;)Lkotlin/properties/ReadWriteProperty;
+	public static synthetic fun doubleArray$default (Lhep/dataforge/meta/MutableItemProvider;[DLhep/dataforge/names/Name;ILjava/lang/Object;)Lkotlin/properties/ReadWriteProperty;
+	public static final fun float (Lhep/dataforge/meta/MutableItemProvider;FLhep/dataforge/names/Name;)Lkotlin/properties/ReadWriteProperty;
+	public static final fun float (Lhep/dataforge/meta/MutableItemProvider;Lhep/dataforge/names/Name;)Lkotlin/properties/ReadWriteProperty;
+	public static synthetic fun float$default (Lhep/dataforge/meta/MutableItemProvider;FLhep/dataforge/names/Name;ILjava/lang/Object;)Lkotlin/properties/ReadWriteProperty;
+	public static synthetic fun float$default (Lhep/dataforge/meta/MutableItemProvider;Lhep/dataforge/names/Name;ILjava/lang/Object;)Lkotlin/properties/ReadWriteProperty;
+	public static final fun int (Lhep/dataforge/meta/MutableItemProvider;ILhep/dataforge/names/Name;)Lkotlin/properties/ReadWriteProperty;
+	public static final fun int (Lhep/dataforge/meta/MutableItemProvider;Lhep/dataforge/names/Name;)Lkotlin/properties/ReadWriteProperty;
+	public static synthetic fun int$default (Lhep/dataforge/meta/MutableItemProvider;ILhep/dataforge/names/Name;ILjava/lang/Object;)Lkotlin/properties/ReadWriteProperty;
+	public static synthetic fun int$default (Lhep/dataforge/meta/MutableItemProvider;Lhep/dataforge/names/Name;ILjava/lang/Object;)Lkotlin/properties/ReadWriteProperty;
+	public static final fun item (Lhep/dataforge/meta/MutableItemProvider;Lhep/dataforge/names/Name;)Lkotlin/properties/ReadWriteProperty;
+	public static synthetic fun item$default (Lhep/dataforge/meta/MutableItemProvider;Lhep/dataforge/names/Name;ILjava/lang/Object;)Lkotlin/properties/ReadWriteProperty;
+	public static final fun listValue (Lhep/dataforge/meta/MutableItemProvider;Lhep/dataforge/names/Name;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;)Lkotlin/properties/ReadWriteProperty;
+	public static synthetic fun listValue$default (Lhep/dataforge/meta/MutableItemProvider;Lhep/dataforge/names/Name;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;ILjava/lang/Object;)Lkotlin/properties/ReadWriteProperty;
+	public static final fun long (Lhep/dataforge/meta/MutableItemProvider;JLhep/dataforge/names/Name;)Lkotlin/properties/ReadWriteProperty;
+	public static final fun long (Lhep/dataforge/meta/MutableItemProvider;Lhep/dataforge/names/Name;)Lkotlin/properties/ReadWriteProperty;
+	public static synthetic fun long$default (Lhep/dataforge/meta/MutableItemProvider;JLhep/dataforge/names/Name;ILjava/lang/Object;)Lkotlin/properties/ReadWriteProperty;
+	public static synthetic fun long$default (Lhep/dataforge/meta/MutableItemProvider;Lhep/dataforge/names/Name;ILjava/lang/Object;)Lkotlin/properties/ReadWriteProperty;
+	public static final fun number (Lhep/dataforge/meta/MutableItemProvider;Lhep/dataforge/names/Name;)Lkotlin/properties/ReadWriteProperty;
+	public static final fun number (Lhep/dataforge/meta/MutableItemProvider;Lhep/dataforge/names/Name;Lkotlin/jvm/functions/Function0;)Lkotlin/properties/ReadWriteProperty;
+	public static final fun number (Lhep/dataforge/meta/MutableItemProvider;Ljava/lang/Number;Lhep/dataforge/names/Name;)Lkotlin/properties/ReadWriteProperty;
+	public static synthetic fun number$default (Lhep/dataforge/meta/MutableItemProvider;Lhep/dataforge/names/Name;ILjava/lang/Object;)Lkotlin/properties/ReadWriteProperty;
+	public static synthetic fun number$default (Lhep/dataforge/meta/MutableItemProvider;Lhep/dataforge/names/Name;Lkotlin/jvm/functions/Function0;ILjava/lang/Object;)Lkotlin/properties/ReadWriteProperty;
+	public static synthetic fun number$default (Lhep/dataforge/meta/MutableItemProvider;Ljava/lang/Number;Lhep/dataforge/names/Name;ILjava/lang/Object;)Lkotlin/properties/ReadWriteProperty;
+	public static final fun numberList (Lhep/dataforge/meta/MutableItemProvider;[Ljava/lang/Number;Lhep/dataforge/names/Name;)Lkotlin/properties/ReadWriteProperty;
+	public static synthetic fun numberList$default (Lhep/dataforge/meta/MutableItemProvider;[Ljava/lang/Number;Lhep/dataforge/names/Name;ILjava/lang/Object;)Lkotlin/properties/ReadWriteProperty;
+	public static final fun string (Lhep/dataforge/meta/MutableItemProvider;Lhep/dataforge/names/Name;)Lkotlin/properties/ReadWriteProperty;
+	public static final fun string (Lhep/dataforge/meta/MutableItemProvider;Lhep/dataforge/names/Name;Lkotlin/jvm/functions/Function0;)Lkotlin/properties/ReadWriteProperty;
+	public static final fun string (Lhep/dataforge/meta/MutableItemProvider;Ljava/lang/String;Lhep/dataforge/names/Name;)Lkotlin/properties/ReadWriteProperty;
+	public static synthetic fun string$default (Lhep/dataforge/meta/MutableItemProvider;Lhep/dataforge/names/Name;ILjava/lang/Object;)Lkotlin/properties/ReadWriteProperty;
+	public static synthetic fun string$default (Lhep/dataforge/meta/MutableItemProvider;Lhep/dataforge/names/Name;Lkotlin/jvm/functions/Function0;ILjava/lang/Object;)Lkotlin/properties/ReadWriteProperty;
+	public static synthetic fun string$default (Lhep/dataforge/meta/MutableItemProvider;Ljava/lang/String;Lhep/dataforge/names/Name;ILjava/lang/Object;)Lkotlin/properties/ReadWriteProperty;
+	public static final fun stringList (Lhep/dataforge/meta/MutableItemProvider;Lhep/dataforge/names/Name;)Lkotlin/properties/ReadWriteProperty;
+	public static final fun stringList (Lhep/dataforge/meta/MutableItemProvider;[Ljava/lang/String;Lhep/dataforge/names/Name;)Lkotlin/properties/ReadWriteProperty;
+	public static synthetic fun stringList$default (Lhep/dataforge/meta/MutableItemProvider;Lhep/dataforge/names/Name;ILjava/lang/Object;)Lkotlin/properties/ReadWriteProperty;
+	public static synthetic fun stringList$default (Lhep/dataforge/meta/MutableItemProvider;[Ljava/lang/String;Lhep/dataforge/names/Name;ILjava/lang/Object;)Lkotlin/properties/ReadWriteProperty;
+	public static final fun value (Lhep/dataforge/meta/MutableItemProvider;Lhep/dataforge/names/Name;)Lkotlin/properties/ReadWriteProperty;
+	public static final fun value (Lhep/dataforge/meta/MutableItemProvider;Lhep/dataforge/names/Name;Lkotlin/jvm/functions/Function0;)Lkotlin/properties/ReadWriteProperty;
+	public static synthetic fun value$default (Lhep/dataforge/meta/MutableItemProvider;Lhep/dataforge/names/Name;ILjava/lang/Object;)Lkotlin/properties/ReadWriteProperty;
+	public static synthetic fun value$default (Lhep/dataforge/meta/MutableItemProvider;Lhep/dataforge/names/Name;Lkotlin/jvm/functions/Function0;ILjava/lang/Object;)Lkotlin/properties/ReadWriteProperty;
+}
+
+public abstract interface class hep/dataforge/meta/MutableItemProvider : hep/dataforge/meta/ItemProvider {
+	public abstract fun setItem (Lhep/dataforge/names/Name;Lhep/dataforge/meta/MetaItem;)V
+}
+
+public final class hep/dataforge/meta/MutableItemProviderKt {
+	public static final fun getItem (Lhep/dataforge/meta/MutableItemProvider;Ljava/lang/String;)Lhep/dataforge/meta/MetaItem;
+	public static final fun node (Lhep/dataforge/meta/MutableItemProvider;Lhep/dataforge/names/Name;)Lkotlin/properties/ReadWriteProperty;
+	public static synthetic fun node$default (Lhep/dataforge/meta/MutableItemProvider;Lhep/dataforge/names/Name;ILjava/lang/Object;)Lkotlin/properties/ReadWriteProperty;
+	public static final fun remove (Lhep/dataforge/meta/MutableItemProvider;Lhep/dataforge/names/Name;)V
+	public static final fun remove (Lhep/dataforge/meta/MutableItemProvider;Ljava/lang/String;)V
+	public static final fun set (Lhep/dataforge/meta/MutableItemProvider;Lhep/dataforge/names/Name;Ljava/lang/Iterable;)V
+	public static final fun set (Lhep/dataforge/meta/MutableItemProvider;Lhep/dataforge/names/Name;Ljava/lang/Object;)V
+	public static final fun set (Lhep/dataforge/meta/MutableItemProvider;Lhep/dataforge/names/NameToken;Ljava/lang/Object;)V
+	public static final fun set (Lhep/dataforge/meta/MutableItemProvider;Ljava/lang/String;Ljava/lang/Iterable;)V
+	public static final fun set (Lhep/dataforge/meta/MutableItemProvider;Ljava/lang/String;Ljava/lang/Object;)V
+	public static final fun set (Lhep/dataforge/meta/MutableItemProvider;Ljava/lang/String;Ljava/lang/String;Ljava/lang/Object;)V
+	public static final fun setIndexed (Lhep/dataforge/meta/MutableItemProvider;Lhep/dataforge/names/Name;Ljava/lang/Iterable;Lkotlin/jvm/functions/Function2;)V
+	public static synthetic fun setIndexed$default (Lhep/dataforge/meta/MutableItemProvider;Lhep/dataforge/names/Name;Ljava/lang/Iterable;Lkotlin/jvm/functions/Function2;ILjava/lang/Object;)V
+	public static final fun setIndexedItems (Lhep/dataforge/meta/MutableItemProvider;Lhep/dataforge/names/Name;Ljava/lang/Iterable;Lkotlin/jvm/functions/Function2;)V
+	public static synthetic fun setIndexedItems$default (Lhep/dataforge/meta/MutableItemProvider;Lhep/dataforge/names/Name;Ljava/lang/Iterable;Lkotlin/jvm/functions/Function2;ILjava/lang/Object;)V
+	public static final fun setItem (Lhep/dataforge/meta/MutableItemProvider;Ljava/lang/String;Lhep/dataforge/meta/MetaItem;)V
+	public static final fun setNode (Lhep/dataforge/meta/MutableItemProvider;Lhep/dataforge/names/Name;Lhep/dataforge/meta/Meta;)V
+	public static final fun setNode (Lhep/dataforge/meta/MutableItemProvider;Ljava/lang/String;Lhep/dataforge/meta/Meta;)V
+	public static final fun setValue (Lhep/dataforge/meta/MutableItemProvider;Lhep/dataforge/names/Name;Lhep/dataforge/values/Value;)V
+	public static final fun setValue (Lhep/dataforge/meta/MutableItemProvider;Ljava/lang/String;Lhep/dataforge/values/Value;)V
+}
+
+public abstract interface class hep/dataforge/meta/MutableMeta : hep/dataforge/meta/MetaNode, hep/dataforge/meta/MutableItemProvider {
+	public abstract fun getItems ()Ljava/util/Map;
+}
+
+public final class hep/dataforge/meta/MutableMeta$DefaultImpls {
+	public static fun getItem (Lhep/dataforge/meta/MutableMeta;Lhep/dataforge/names/Name;)Lhep/dataforge/meta/MetaItem;
+	public static fun toMeta (Lhep/dataforge/meta/MutableMeta;)Lhep/dataforge/meta/Meta;
+}
+
+public final class hep/dataforge/meta/MutableMetaKt {
+	public static final fun append (Lhep/dataforge/meta/MutableMeta;Lhep/dataforge/names/Name;Ljava/lang/Object;)V
+	public static final fun append (Lhep/dataforge/meta/MutableMeta;Ljava/lang/String;Ljava/lang/Object;)V
+	public static final fun edit (Lhep/dataforge/meta/AbstractMutableMeta;Lhep/dataforge/names/Name;Lkotlin/jvm/functions/Function1;)V
+	public static final fun update (Lhep/dataforge/meta/MutableMeta;Lhep/dataforge/meta/Meta;)V
+}
+
+public abstract interface class hep/dataforge/meta/ObservableMeta : hep/dataforge/meta/Meta {
+	public abstract fun onChange (Ljava/lang/Object;Lkotlin/jvm/functions/Function3;)V
+	public abstract fun removeListener (Ljava/lang/Object;)V
+}
+
+public final class hep/dataforge/meta/ObservableMeta$DefaultImpls {
+	public static fun getItem (Lhep/dataforge/meta/ObservableMeta;Lhep/dataforge/names/Name;)Lhep/dataforge/meta/MetaItem;
+	public static fun toMeta (Lhep/dataforge/meta/ObservableMeta;)Lhep/dataforge/meta/Meta;
+}
+
+public class hep/dataforge/meta/Scheme : hep/dataforge/meta/Configurable, hep/dataforge/meta/MetaRepr, hep/dataforge/meta/MutableItemProvider, hep/dataforge/meta/descriptors/Described {
+	public fun <init> ()V
+	public fun <init> (Lhep/dataforge/meta/Config;Lhep/dataforge/meta/ItemProvider;Lhep/dataforge/meta/descriptors/NodeDescriptor;)V
+	public synthetic fun <init> (Lhep/dataforge/meta/Config;Lhep/dataforge/meta/ItemProvider;Lhep/dataforge/meta/descriptors/NodeDescriptor;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
+	public fun getConfig ()Lhep/dataforge/meta/Config;
+	public final fun getDefaultItem (Lhep/dataforge/names/Name;)Lhep/dataforge/meta/MetaItem;
+	public fun getDefaultLayer ()Lhep/dataforge/meta/Meta;
+	public synthetic fun getDescriptor ()Lhep/dataforge/meta/descriptors/ItemDescriptor;
+	public fun getDescriptor ()Lhep/dataforge/meta/descriptors/NodeDescriptor;
+	public fun getItem (Lhep/dataforge/names/Name;)Lhep/dataforge/meta/MetaItem;
+	public final fun isEmpty ()Z
+	public fun setItem (Lhep/dataforge/names/Name;Lhep/dataforge/meta/MetaItem;)V
+	public fun toMeta ()Lhep/dataforge/meta/Laminate;
+	public synthetic fun toMeta ()Lhep/dataforge/meta/Meta;
+	public final fun validateItem (Lhep/dataforge/names/Name;Lhep/dataforge/meta/MetaItem;)Z
+}
+
+public final class hep/dataforge/meta/SchemeKt {
+	public static final fun asScheme (Lhep/dataforge/meta/Meta;)Lhep/dataforge/meta/Scheme;
+	public static final fun invoke (Lhep/dataforge/meta/Scheme;Lkotlin/jvm/functions/Function1;)Lhep/dataforge/meta/Scheme;
+	public static final fun toScheme (Lhep/dataforge/meta/Meta;Lhep/dataforge/meta/Specification;Lkotlin/jvm/functions/Function1;)Lhep/dataforge/meta/MutableItemProvider;
+	public static synthetic fun toScheme$default (Lhep/dataforge/meta/Meta;Lhep/dataforge/meta/Specification;Lkotlin/jvm/functions/Function1;ILjava/lang/Object;)Lhep/dataforge/meta/MutableItemProvider;
+}
+
+public class hep/dataforge/meta/SchemeSpec : hep/dataforge/meta/Specification, hep/dataforge/meta/descriptors/Described {
+	public fun <init> (Lkotlin/jvm/functions/Function0;)V
+	public fun <init> (Lkotlin/jvm/functions/Function3;)V
+	public synthetic fun empty ()Lhep/dataforge/meta/MutableItemProvider;
+	public fun empty ()Lhep/dataforge/meta/Scheme;
+	public synthetic fun getDescriptor ()Lhep/dataforge/meta/descriptors/ItemDescriptor;
+	public fun getDescriptor ()Lhep/dataforge/meta/descriptors/NodeDescriptor;
+	public synthetic fun invoke (Lkotlin/jvm/functions/Function1;)Lhep/dataforge/meta/MutableItemProvider;
+	public final fun invoke (Lkotlin/jvm/functions/Function1;)Lhep/dataforge/meta/Scheme;
+	public synthetic fun read (Lhep/dataforge/meta/Meta;Lhep/dataforge/meta/ItemProvider;)Lhep/dataforge/meta/MutableItemProvider;
+	public fun read (Lhep/dataforge/meta/Meta;Lhep/dataforge/meta/ItemProvider;)Lhep/dataforge/meta/Scheme;
+	public synthetic fun wrap (Lhep/dataforge/meta/Config;Lhep/dataforge/meta/ItemProvider;)Lhep/dataforge/meta/MutableItemProvider;
+	public fun wrap (Lhep/dataforge/meta/Config;Lhep/dataforge/meta/ItemProvider;)Lhep/dataforge/meta/Scheme;
+}
+
+public final class hep/dataforge/meta/SealedMeta : hep/dataforge/meta/AbstractMetaNode {
+	public fun getItems ()Ljava/util/Map;
+}
+
+public abstract interface class hep/dataforge/meta/Specification {
+	public abstract fun empty ()Lhep/dataforge/meta/MutableItemProvider;
+	public abstract fun invoke (Lkotlin/jvm/functions/Function1;)Lhep/dataforge/meta/MutableItemProvider;
+	public abstract fun read (Lhep/dataforge/meta/Meta;Lhep/dataforge/meta/ItemProvider;)Lhep/dataforge/meta/MutableItemProvider;
+	public abstract fun wrap (Lhep/dataforge/meta/Config;Lhep/dataforge/meta/ItemProvider;)Lhep/dataforge/meta/MutableItemProvider;
+}
+
+public final class hep/dataforge/meta/Specification$DefaultImpls {
+	public static fun empty (Lhep/dataforge/meta/Specification;)Lhep/dataforge/meta/MutableItemProvider;
+	public static fun invoke (Lhep/dataforge/meta/Specification;Lkotlin/jvm/functions/Function1;)Lhep/dataforge/meta/MutableItemProvider;
+	public static synthetic fun read$default (Lhep/dataforge/meta/Specification;Lhep/dataforge/meta/Meta;Lhep/dataforge/meta/ItemProvider;ILjava/lang/Object;)Lhep/dataforge/meta/MutableItemProvider;
+	public static fun wrap (Lhep/dataforge/meta/Specification;Lhep/dataforge/meta/Config;Lhep/dataforge/meta/ItemProvider;)Lhep/dataforge/meta/MutableItemProvider;
+	public static synthetic fun wrap$default (Lhep/dataforge/meta/Specification;Lhep/dataforge/meta/Config;Lhep/dataforge/meta/ItemProvider;ILjava/lang/Object;)Lhep/dataforge/meta/MutableItemProvider;
+}
+
+public final class hep/dataforge/meta/SpecificationKt {
+	public static final fun configSpec (Lhep/dataforge/meta/MetaItem;Lhep/dataforge/meta/Specification;)Lhep/dataforge/meta/MutableItemProvider;
+	public static final fun configure (Lhep/dataforge/meta/MetaRepr;Lhep/dataforge/meta/Specification;Lkotlin/jvm/functions/Function1;)Lhep/dataforge/meta/MetaRepr;
+	public static final fun createStyle (Lhep/dataforge/meta/Specification;Lkotlin/jvm/functions/Function1;)Lhep/dataforge/meta/Meta;
+	public static final fun spec (Lhep/dataforge/meta/MetaItem;Lhep/dataforge/meta/Specification;)Lhep/dataforge/meta/MutableItemProvider;
+	public static final fun spec (Lhep/dataforge/meta/MutableItemProvider;Lhep/dataforge/meta/Specification;Lhep/dataforge/meta/Scheme;Lhep/dataforge/names/Name;)Lkotlin/properties/ReadWriteProperty;
+	public static final fun spec (Lhep/dataforge/meta/MutableItemProvider;Lhep/dataforge/meta/Specification;Lhep/dataforge/names/Name;)Lkotlin/properties/ReadWriteProperty;
+	public static synthetic fun spec$default (Lhep/dataforge/meta/MutableItemProvider;Lhep/dataforge/meta/Specification;Lhep/dataforge/meta/Scheme;Lhep/dataforge/names/Name;ILjava/lang/Object;)Lkotlin/properties/ReadWriteProperty;
+	public static synthetic fun spec$default (Lhep/dataforge/meta/MutableItemProvider;Lhep/dataforge/meta/Specification;Lhep/dataforge/names/Name;ILjava/lang/Object;)Lkotlin/properties/ReadWriteProperty;
+	public static final fun update (Lhep/dataforge/meta/Configurable;Lhep/dataforge/meta/Specification;Lkotlin/jvm/functions/Function1;)Lhep/dataforge/meta/Configurable;
+	public static final fun update (Lhep/dataforge/meta/Specification;Lhep/dataforge/meta/Meta;Lkotlin/jvm/functions/Function1;)Lhep/dataforge/meta/MutableItemProvider;
+}
+
+public abstract interface class hep/dataforge/meta/descriptors/Described {
+	public static final field Companion Lhep/dataforge/meta/descriptors/Described$Companion;
+	public abstract fun getDescriptor ()Lhep/dataforge/meta/descriptors/ItemDescriptor;
+}
+
+public final class hep/dataforge/meta/descriptors/Described$Companion {
+}
+
+public final class hep/dataforge/meta/descriptors/DescriptorMetaKt {
+	public static final fun defaultItem (Lhep/dataforge/meta/descriptors/ItemDescriptor;)Lhep/dataforge/meta/MetaItem;
+	public static final fun defaultMeta (Lhep/dataforge/meta/descriptors/NodeDescriptor;)Lhep/dataforge/meta/Laminate;
+}
+
+public abstract class hep/dataforge/meta/descriptors/ItemDescriptor {
+	public static final field Companion Lhep/dataforge/meta/descriptors/ItemDescriptor$Companion;
+	public static final field DEFAULT_INDEX_KEY Ljava/lang/String;
+	public synthetic fun <init> (Lhep/dataforge/meta/Config;Lkotlin/jvm/internal/DefaultConstructorMarker;)V
+	public final fun getAttributes ()Lhep/dataforge/meta/Config;
+	public final fun getConfig ()Lhep/dataforge/meta/Config;
+	public final fun getIndexKey ()Ljava/lang/String;
+	public final fun getInfo ()Ljava/lang/String;
+	public final fun getMultiple ()Z
+	public abstract fun getRequired ()Z
+	public final fun setAttributes (Lhep/dataforge/meta/Config;)V
+	public final fun setIndexKey (Ljava/lang/String;)V
+	public final fun setInfo (Ljava/lang/String;)V
+	public final fun setMultiple (Z)V
+	public abstract fun setRequired (Z)V
+}
+
+public final class hep/dataforge/meta/descriptors/ItemDescriptor$Companion {
+}
+
+public final class hep/dataforge/meta/descriptors/ItemDescriptorKt {
+	public static final fun attributes (Lhep/dataforge/meta/descriptors/ItemDescriptor;Lkotlin/jvm/functions/Function1;)V
+	public static final fun get (Lhep/dataforge/meta/descriptors/ItemDescriptor;Lhep/dataforge/names/Name;)Lhep/dataforge/meta/descriptors/ItemDescriptor;
+	public static final fun get (Lhep/dataforge/meta/descriptors/ItemDescriptor;Ljava/lang/String;)Lhep/dataforge/meta/descriptors/ItemDescriptor;
+	public static final fun plus (Lhep/dataforge/meta/descriptors/NodeDescriptor;Lhep/dataforge/meta/descriptors/NodeDescriptor;)Lhep/dataforge/meta/descriptors/NodeDescriptor;
+	public static final fun validateItem (Lhep/dataforge/meta/descriptors/ItemDescriptor;Lhep/dataforge/meta/MetaItem;)Z
+}
+
+public final class hep/dataforge/meta/descriptors/NodeDescriptor : hep/dataforge/meta/descriptors/ItemDescriptor {
+	public static final field Companion Lhep/dataforge/meta/descriptors/NodeDescriptor$Companion;
+	public fun <init> ()V
+	public fun <init> (Lhep/dataforge/meta/Config;)V
+	public synthetic fun <init> (Lhep/dataforge/meta/Config;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
+	public final fun getDefault ()Lhep/dataforge/meta/Config;
+	public final fun getItems ()Ljava/util/Map;
+	public final fun getNodes ()Ljava/util/Map;
+	public fun getRequired ()Z
+	public final fun getValues ()Ljava/util/Map;
+	public final fun item (Lhep/dataforge/names/Name;Lhep/dataforge/meta/descriptors/ItemDescriptor;)V
+	public final fun item (Ljava/lang/String;Lhep/dataforge/meta/descriptors/ItemDescriptor;)V
+	public final fun node (Lhep/dataforge/names/Name;Lkotlin/jvm/functions/Function1;)V
+	public final fun node (Ljava/lang/String;Lkotlin/jvm/functions/Function1;)V
+	public final fun setDefault (Lhep/dataforge/meta/Config;)V
+	public fun setRequired (Z)V
+	public final fun value (Lhep/dataforge/names/Name;Lkotlin/jvm/functions/Function1;)V
+	public final fun value (Ljava/lang/String;Lkotlin/jvm/functions/Function1;)V
+}
+
+public final class hep/dataforge/meta/descriptors/NodeDescriptor$Companion {
+	public final fun invoke (Lkotlin/jvm/functions/Function1;)Lhep/dataforge/meta/descriptors/NodeDescriptor;
+}
+
+public final class hep/dataforge/meta/descriptors/ValueDescriptor : hep/dataforge/meta/descriptors/ItemDescriptor {
+	public fun <init> ()V
+	public fun <init> (Lhep/dataforge/meta/Config;)V
+	public synthetic fun <init> (Lhep/dataforge/meta/Config;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
+	public final fun allow ([Ljava/lang/Object;)V
+	public final fun default (Ljava/lang/Object;)V
+	public final fun getAllowedValues ()Ljava/util/List;
+	public final fun getDefault ()Lhep/dataforge/values/Value;
+	public fun getRequired ()Z
+	public final fun getType ()Ljava/util/List;
+	public final fun isAllowedValue (Lhep/dataforge/values/Value;)Z
+	public final fun setAllowedValues (Ljava/util/List;)V
+	public final fun setDefault (Lhep/dataforge/values/Value;)V
+	public fun setRequired (Z)V
+	public final fun setType (Ljava/util/List;)V
+	public final fun type ([Lhep/dataforge/values/ValueType;)V
+}
+
+public final class hep/dataforge/meta/transformations/KeepTransformationRule : hep/dataforge/meta/transformations/TransformationRule {
+	public fun <init> (Lkotlin/jvm/functions/Function1;)V
+	public final fun component1 ()Lkotlin/jvm/functions/Function1;
+	public final fun copy (Lkotlin/jvm/functions/Function1;)Lhep/dataforge/meta/transformations/KeepTransformationRule;
+	public static synthetic fun copy$default (Lhep/dataforge/meta/transformations/KeepTransformationRule;Lkotlin/jvm/functions/Function1;ILjava/lang/Object;)Lhep/dataforge/meta/transformations/KeepTransformationRule;
+	public fun equals (Ljava/lang/Object;)Z
+	public final fun getSelector ()Lkotlin/jvm/functions/Function1;
+	public fun hashCode ()I
+	public fun matches (Lhep/dataforge/names/Name;Lhep/dataforge/meta/MetaItem;)Z
+	public fun selectItems (Lhep/dataforge/meta/Meta;)Lkotlin/sequences/Sequence;
+	public fun toString ()Ljava/lang/String;
+	public fun transformItem (Lhep/dataforge/names/Name;Lhep/dataforge/meta/MetaItem;Lhep/dataforge/meta/MutableMeta;)V
+}
+
+public abstract interface class hep/dataforge/meta/transformations/MetaConverter {
+	public static final field Companion Lhep/dataforge/meta/transformations/MetaConverter$Companion;
+	public abstract fun itemToObject (Lhep/dataforge/meta/MetaItem;)Ljava/lang/Object;
+	public abstract fun objectToMetaItem (Ljava/lang/Object;)Lhep/dataforge/meta/MetaItem;
+}
+
+public final class hep/dataforge/meta/transformations/MetaConverter$Companion {
+	public final fun getBoolean ()Lhep/dataforge/meta/transformations/MetaConverter;
+	public final fun getDouble ()Lhep/dataforge/meta/transformations/MetaConverter;
+	public final fun getFloat ()Lhep/dataforge/meta/transformations/MetaConverter;
+	public final fun getInt ()Lhep/dataforge/meta/transformations/MetaConverter;
+	public final fun getItem ()Lhep/dataforge/meta/transformations/MetaConverter;
+	public final fun getLong ()Lhep/dataforge/meta/transformations/MetaConverter;
+	public final fun getMeta ()Lhep/dataforge/meta/transformations/MetaConverter;
+	public final fun getNumber ()Lhep/dataforge/meta/transformations/MetaConverter;
+	public final fun getString ()Lhep/dataforge/meta/transformations/MetaConverter;
+	public final fun getValue ()Lhep/dataforge/meta/transformations/MetaConverter;
+	public final fun valueList (Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;)Lhep/dataforge/meta/transformations/MetaConverter;
+	public static synthetic fun valueList$default (Lhep/dataforge/meta/transformations/MetaConverter$Companion;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;ILjava/lang/Object;)Lhep/dataforge/meta/transformations/MetaConverter;
+}
+
+public final class hep/dataforge/meta/transformations/MetaConverterKt {
+	public static final fun metaToObject (Lhep/dataforge/meta/transformations/MetaConverter;Lhep/dataforge/meta/Meta;)Ljava/lang/Object;
+	public static final fun nullableItemToObject (Lhep/dataforge/meta/transformations/MetaConverter;Lhep/dataforge/meta/MetaItem;)Ljava/lang/Object;
+	public static final fun nullableObjectToMetaItem (Lhep/dataforge/meta/transformations/MetaConverter;Ljava/lang/Object;)Lhep/dataforge/meta/MetaItem;
+	public static final fun valueToObject (Lhep/dataforge/meta/transformations/MetaConverter;Lhep/dataforge/values/Value;)Ljava/lang/Object;
+}
+
+public final class hep/dataforge/meta/transformations/MetaTransformation {
+	public static final field Companion Lhep/dataforge/meta/transformations/MetaTransformation$Companion;
+	public static final fun apply-impl (Ljava/util/Collection;Lhep/dataforge/meta/Meta;)Lhep/dataforge/meta/Meta;
+	public static final fun bind-impl (Ljava/util/Collection;Lhep/dataforge/meta/Config;Lhep/dataforge/meta/MutableMeta;)V
+	public static final synthetic fun box-impl (Ljava/util/Collection;)Lhep/dataforge/meta/transformations/MetaTransformation;
+	public static fun constructor-impl (Ljava/util/Collection;)Ljava/util/Collection;
+	public fun equals (Ljava/lang/Object;)Z
+	public static fun equals-impl (Ljava/util/Collection;Ljava/lang/Object;)Z
+	public static final fun equals-impl0 (Ljava/util/Collection;Ljava/util/Collection;)Z
+	public static final fun generate-impl (Ljava/util/Collection;Lhep/dataforge/meta/Config;)Lhep/dataforge/meta/ObservableMeta;
+	public static final fun generate-impl (Ljava/util/Collection;Lhep/dataforge/meta/Meta;)Lhep/dataforge/meta/Meta;
+	public final fun getTransformations ()Ljava/util/Collection;
+	public fun hashCode ()I
+	public static fun hashCode-impl (Ljava/util/Collection;)I
+	public fun toString ()Ljava/lang/String;
+	public static fun toString-impl (Ljava/util/Collection;)Ljava/lang/String;
+	public final synthetic fun unbox-impl ()Ljava/util/Collection;
+}
+
+public final class hep/dataforge/meta/transformations/MetaTransformation$Companion {
+	public final fun make-S5KKvQA (Lkotlin/jvm/functions/Function1;)Ljava/util/Collection;
+}
+
+public final class hep/dataforge/meta/transformations/MetaTransformationBuilder {
+	public fun <init> ()V
+	public final fun build-S5KKvQA ()Ljava/util/Collection;
+	public final fun keep (Lhep/dataforge/names/Name;)V
+	public final fun keep (Ljava/lang/String;)V
+	public final fun keep (Lkotlin/jvm/functions/Function1;)V
+	public final fun move (Lhep/dataforge/names/Name;Lhep/dataforge/names/Name;Lkotlin/jvm/functions/Function1;)V
+	public static synthetic fun move$default (Lhep/dataforge/meta/transformations/MetaTransformationBuilder;Lhep/dataforge/names/Name;Lhep/dataforge/names/Name;Lkotlin/jvm/functions/Function1;ILjava/lang/Object;)V
+}
+
+public final class hep/dataforge/meta/transformations/RegexItemTransformationRule : hep/dataforge/meta/transformations/TransformationRule {
+	public fun <init> (Lkotlin/text/Regex;Lkotlin/jvm/functions/Function4;)V
+	public final fun component1 ()Lkotlin/text/Regex;
+	public final fun component2 ()Lkotlin/jvm/functions/Function4;
+	public final fun copy (Lkotlin/text/Regex;Lkotlin/jvm/functions/Function4;)Lhep/dataforge/meta/transformations/RegexItemTransformationRule;
+	public static synthetic fun copy$default (Lhep/dataforge/meta/transformations/RegexItemTransformationRule;Lkotlin/text/Regex;Lkotlin/jvm/functions/Function4;ILjava/lang/Object;)Lhep/dataforge/meta/transformations/RegexItemTransformationRule;
+	public fun equals (Ljava/lang/Object;)Z
+	public final fun getFrom ()Lkotlin/text/Regex;
+	public final fun getTransform ()Lkotlin/jvm/functions/Function4;
+	public fun hashCode ()I
+	public fun matches (Lhep/dataforge/names/Name;Lhep/dataforge/meta/MetaItem;)Z
+	public fun selectItems (Lhep/dataforge/meta/Meta;)Lkotlin/sequences/Sequence;
+	public fun toString ()Ljava/lang/String;
+	public fun transformItem (Lhep/dataforge/names/Name;Lhep/dataforge/meta/MetaItem;Lhep/dataforge/meta/MutableMeta;)V
+}
+
+public final class hep/dataforge/meta/transformations/SingleItemTransformationRule : hep/dataforge/meta/transformations/TransformationRule {
+	public fun <init> (Lhep/dataforge/names/Name;Lkotlin/jvm/functions/Function3;)V
+	public final fun component1 ()Lhep/dataforge/names/Name;
+	public final fun component2 ()Lkotlin/jvm/functions/Function3;
+	public final fun copy (Lhep/dataforge/names/Name;Lkotlin/jvm/functions/Function3;)Lhep/dataforge/meta/transformations/SingleItemTransformationRule;
+	public static synthetic fun copy$default (Lhep/dataforge/meta/transformations/SingleItemTransformationRule;Lhep/dataforge/names/Name;Lkotlin/jvm/functions/Function3;ILjava/lang/Object;)Lhep/dataforge/meta/transformations/SingleItemTransformationRule;
+	public fun equals (Ljava/lang/Object;)Z
+	public final fun getFrom ()Lhep/dataforge/names/Name;
+	public final fun getTransform ()Lkotlin/jvm/functions/Function3;
+	public fun hashCode ()I
+	public fun matches (Lhep/dataforge/names/Name;Lhep/dataforge/meta/MetaItem;)Z
+	public fun selectItems (Lhep/dataforge/meta/Meta;)Lkotlin/sequences/Sequence;
+	public fun toString ()Ljava/lang/String;
+	public fun transformItem (Lhep/dataforge/names/Name;Lhep/dataforge/meta/MetaItem;Lhep/dataforge/meta/MutableMeta;)V
+}
+
+public abstract interface class hep/dataforge/meta/transformations/TransformationRule {
+	public abstract fun matches (Lhep/dataforge/names/Name;Lhep/dataforge/meta/MetaItem;)Z
+	public abstract fun selectItems (Lhep/dataforge/meta/Meta;)Lkotlin/sequences/Sequence;
+	public abstract fun transformItem (Lhep/dataforge/names/Name;Lhep/dataforge/meta/MetaItem;Lhep/dataforge/meta/MutableMeta;)V
+}
+
+public final class hep/dataforge/meta/transformations/TransformationRule$DefaultImpls {
+	public static fun selectItems (Lhep/dataforge/meta/transformations/TransformationRule;Lhep/dataforge/meta/Meta;)Lkotlin/sequences/Sequence;
+}
+
+public final class hep/dataforge/names/Name {
+	public static final field Companion Lhep/dataforge/names/Name$Companion;
+	public static final field NAME_SEPARATOR Ljava/lang/String;
+	public fun <init> (Ljava/util/List;)V
+	public fun equals (Ljava/lang/Object;)Z
+	public final fun getTokens ()Ljava/util/List;
+	public fun hashCode ()I
+	public fun toString ()Ljava/lang/String;
+}
+
+public final class hep/dataforge/names/Name$Companion : kotlinx/serialization/KSerializer {
+	public fun deserialize (Lkotlinx/serialization/encoding/Decoder;)Lhep/dataforge/names/Name;
+	public synthetic fun deserialize (Lkotlinx/serialization/encoding/Decoder;)Ljava/lang/Object;
+	public fun getDescriptor ()Lkotlinx/serialization/descriptors/SerialDescriptor;
+	public final fun getEMPTY ()Lhep/dataforge/names/Name;
+	public fun serialize (Lkotlinx/serialization/encoding/Encoder;Lhep/dataforge/names/Name;)V
+	public synthetic fun serialize (Lkotlinx/serialization/encoding/Encoder;Ljava/lang/Object;)V
+	public final fun serializer ()Lkotlinx/serialization/KSerializer;
+}
+
+public final class hep/dataforge/names/NameKt {
+	public static final fun appendLeft (Lhep/dataforge/names/Name;Ljava/lang/String;)Lhep/dataforge/names/Name;
+	public static final fun asName (Lhep/dataforge/names/NameToken;)Lhep/dataforge/names/Name;
+	public static final fun asName (Ljava/lang/String;)Lhep/dataforge/names/Name;
+	public static final fun cutFirst (Lhep/dataforge/names/Name;)Lhep/dataforge/names/Name;
+	public static final fun cutLast (Lhep/dataforge/names/Name;)Lhep/dataforge/names/Name;
+	public static final fun endsWith (Lhep/dataforge/names/Name;Lhep/dataforge/names/Name;)Z
+	public static final fun endsWith (Lhep/dataforge/names/Name;Lhep/dataforge/names/NameToken;)Z
+	public static final fun firstOrNull (Lhep/dataforge/names/Name;)Lhep/dataforge/names/NameToken;
+	public static final fun get (Lhep/dataforge/names/Name;I)Lhep/dataforge/names/NameToken;
+	public static final fun get (Ljava/util/Map;Ljava/lang/String;)Ljava/lang/Object;
+	public static final fun get (Ljava/util/Map;Ljava/lang/String;Ljava/lang/String;)Ljava/lang/Object;
+	public static synthetic fun get$default (Ljava/util/Map;Ljava/lang/String;Ljava/lang/String;ILjava/lang/Object;)Ljava/lang/Object;
+	public static final fun getLength (Lhep/dataforge/names/Name;)I
+	public static final fun isEmpty (Lhep/dataforge/names/Name;)Z
+	public static final fun lastOrNull (Lhep/dataforge/names/Name;)Lhep/dataforge/names/NameToken;
+	public static final fun plus (Lhep/dataforge/names/Name;Lhep/dataforge/names/Name;)Lhep/dataforge/names/Name;
+	public static final fun plus (Lhep/dataforge/names/Name;Lhep/dataforge/names/NameToken;)Lhep/dataforge/names/Name;
+	public static final fun plus (Lhep/dataforge/names/Name;Ljava/lang/String;)Lhep/dataforge/names/Name;
+	public static final fun plus (Lhep/dataforge/names/NameToken;Lhep/dataforge/names/Name;)Lhep/dataforge/names/Name;
+	public static final fun set (Ljava/util/Map;Ljava/lang/String;Ljava/lang/Object;)V
+	public static final fun startsWith (Lhep/dataforge/names/Name;Lhep/dataforge/names/Name;)Z
+	public static final fun startsWith (Lhep/dataforge/names/Name;Lhep/dataforge/names/NameToken;)Z
+	public static final fun toName (Ljava/lang/String;)Lhep/dataforge/names/Name;
+	public static final fun withIndex (Lhep/dataforge/names/Name;Ljava/lang/String;)Lhep/dataforge/names/Name;
+}
+
+public final class hep/dataforge/names/NameToken {
+	public static final field Companion Lhep/dataforge/names/NameToken$Companion;
+	public fun <init> (Ljava/lang/String;Ljava/lang/String;)V
+	public synthetic fun <init> (Ljava/lang/String;Ljava/lang/String;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
+	public final fun component1 ()Ljava/lang/String;
+	public final fun component2 ()Ljava/lang/String;
+	public final fun copy (Ljava/lang/String;Ljava/lang/String;)Lhep/dataforge/names/NameToken;
+	public static synthetic fun copy$default (Lhep/dataforge/names/NameToken;Ljava/lang/String;Ljava/lang/String;ILjava/lang/Object;)Lhep/dataforge/names/NameToken;
+	public fun equals (Ljava/lang/Object;)Z
+	public final fun getBody ()Ljava/lang/String;
+	public final fun getIndex ()Ljava/lang/String;
+	public fun hashCode ()I
+	public fun toString ()Ljava/lang/String;
+}
+
+public final class hep/dataforge/names/NameToken$Companion : kotlinx/serialization/KSerializer {
+	public fun deserialize (Lkotlinx/serialization/encoding/Decoder;)Lhep/dataforge/names/NameToken;
+	public synthetic fun deserialize (Lkotlinx/serialization/encoding/Decoder;)Ljava/lang/Object;
+	public fun getDescriptor ()Lkotlinx/serialization/descriptors/SerialDescriptor;
+	public fun serialize (Lkotlinx/serialization/encoding/Encoder;Lhep/dataforge/names/NameToken;)V
+	public synthetic fun serialize (Lkotlinx/serialization/encoding/Encoder;Ljava/lang/Object;)V
+	public final fun serializer ()Lkotlinx/serialization/KSerializer;
+}
+
+public final class hep/dataforge/names/NameTokenKt {
+	public static final fun hasIndex (Lhep/dataforge/names/NameToken;)Z
+	public static final fun withIndex (Lhep/dataforge/names/NameToken;Ljava/lang/String;)Lhep/dataforge/names/NameToken;
+}
+
+public final class hep/dataforge/values/DoubleArrayValue : hep/dataforge/values/Value {
+	public fun <init> ([D)V
+	public fun equals (Ljava/lang/Object;)Z
+	public fun getList ()Ljava/util/List;
+	public fun getNumber ()Ljava/lang/Double;
+	public synthetic fun getNumber ()Ljava/lang/Number;
+	public fun getString ()Ljava/lang/String;
+	public fun getType ()Lhep/dataforge/values/ValueType;
+	public synthetic fun getValue ()Ljava/lang/Object;
+	public fun getValue ()[D
+	public fun hashCode ()I
+	public fun toString ()Ljava/lang/String;
+}
+
+public final class hep/dataforge/values/EnumValue : hep/dataforge/values/Value {
+	public fun <init> (Ljava/lang/Enum;)V
+	public fun equals (Ljava/lang/Object;)Z
+	public fun getList ()Ljava/util/List;
+	public fun getNumber ()Ljava/lang/Number;
+	public fun getString ()Ljava/lang/String;
+	public fun getType ()Lhep/dataforge/values/ValueType;
+	public fun getValue ()Ljava/lang/Enum;
+	public synthetic fun getValue ()Ljava/lang/Object;
+	public fun hashCode ()I
+	public fun toString ()Ljava/lang/String;
+}
+
+public final class hep/dataforge/values/ExoticValuesKt {
+	public static final fun asValue ([D)Lhep/dataforge/values/Value;
+	public static final fun lazyParseValue (Ljava/lang/String;)Lhep/dataforge/values/LazyParsedValue;
+}
+
+public final class hep/dataforge/values/False : hep/dataforge/values/Value {
+	public static final field INSTANCE Lhep/dataforge/values/False;
+	public fun equals (Ljava/lang/Object;)Z
+	public fun getList ()Ljava/util/List;
+	public fun getNumber ()Ljava/lang/Number;
+	public fun getString ()Ljava/lang/String;
+	public fun getType ()Lhep/dataforge/values/ValueType;
+	public fun getValue ()Ljava/lang/Object;
+	public fun hashCode ()I
+	public fun toString ()Ljava/lang/String;
+}
+
+public final class hep/dataforge/values/LazyParsedValue : hep/dataforge/values/Value {
+	public fun <init> (Ljava/lang/String;)V
+	public fun equals (Ljava/lang/Object;)Z
+	public fun getList ()Ljava/util/List;
+	public fun getNumber ()Ljava/lang/Number;
+	public fun getString ()Ljava/lang/String;
+	public fun getType ()Lhep/dataforge/values/ValueType;
+	public fun getValue ()Ljava/lang/Object;
+	public fun hashCode ()I
+	public fun toString ()Ljava/lang/String;
+}
+
+public final class hep/dataforge/values/ListValue : hep/dataforge/values/Value {
+	public fun <init> (Ljava/util/List;)V
+	public fun equals (Ljava/lang/Object;)Z
+	public fun getList ()Ljava/util/List;
+	public fun getNumber ()Ljava/lang/Number;
+	public fun getString ()Ljava/lang/String;
+	public fun getType ()Lhep/dataforge/values/ValueType;
+	public synthetic fun getValue ()Ljava/lang/Object;
+	public fun getValue ()Ljava/util/List;
+	public fun hashCode ()I
+	public fun toString ()Ljava/lang/String;
+}
+
+public final class hep/dataforge/values/Null : hep/dataforge/values/Value {
+	public static final field INSTANCE Lhep/dataforge/values/Null;
+	public fun equals (Ljava/lang/Object;)Z
+	public fun getList ()Ljava/util/List;
+	public fun getNumber ()Ljava/lang/Number;
+	public fun getString ()Ljava/lang/String;
+	public fun getType ()Lhep/dataforge/values/ValueType;
+	public fun getValue ()Ljava/lang/Object;
+	public fun hashCode ()I
+	public fun toString ()Ljava/lang/String;
+}
+
+public final class hep/dataforge/values/NumberValue : hep/dataforge/values/Value {
+	public fun <init> (Ljava/lang/Number;)V
+	public fun equals (Ljava/lang/Object;)Z
+	public fun getList ()Ljava/util/List;
+	public fun getNumber ()Ljava/lang/Number;
+	public fun getString ()Ljava/lang/String;
+	public fun getType ()Lhep/dataforge/values/ValueType;
+	public fun getValue ()Ljava/lang/Object;
+	public fun hashCode ()I
+	public fun toString ()Ljava/lang/String;
+}
+
+public final class hep/dataforge/values/StringValue : hep/dataforge/values/Value {
+	public fun <init> (Ljava/lang/String;)V
+	public fun equals (Ljava/lang/Object;)Z
+	public fun getList ()Ljava/util/List;
+	public fun getNumber ()Ljava/lang/Number;
+	public fun getString ()Ljava/lang/String;
+	public fun getType ()Lhep/dataforge/values/ValueType;
+	public fun getValue ()Ljava/lang/Object;
+	public fun hashCode ()I
+	public fun toString ()Ljava/lang/String;
+}
+
+public final class hep/dataforge/values/True : hep/dataforge/values/Value {
+	public static final field INSTANCE Lhep/dataforge/values/True;
+	public fun equals (Ljava/lang/Object;)Z
+	public fun getList ()Ljava/util/List;
+	public fun getNumber ()Ljava/lang/Number;
+	public fun getString ()Ljava/lang/String;
+	public fun getType ()Lhep/dataforge/values/ValueType;
+	public fun getValue ()Ljava/lang/Object;
+	public fun hashCode ()I
+	public fun toString ()Ljava/lang/String;
+}
+
+public abstract interface class hep/dataforge/values/Value {
+	public static final field Companion Lhep/dataforge/values/Value$Companion;
+	public static final field TARGET Ljava/lang/String;
+	public abstract fun equals (Ljava/lang/Object;)Z
+	public abstract fun getList ()Ljava/util/List;
+	public abstract fun getNumber ()Ljava/lang/Number;
+	public abstract fun getString ()Ljava/lang/String;
+	public abstract fun getType ()Lhep/dataforge/values/ValueType;
+	public abstract fun getValue ()Ljava/lang/Object;
+	public abstract fun hashCode ()I
+}
+
+public final class hep/dataforge/values/Value$Companion {
+	public static final field TARGET Ljava/lang/String;
+	public final fun of (Ljava/lang/Object;)Lhep/dataforge/values/Value;
+}
+
+public final class hep/dataforge/values/Value$DefaultImpls {
+	public static fun getList (Lhep/dataforge/values/Value;)Ljava/util/List;
+}
+
+public final class hep/dataforge/values/ValueExtensionsKt {
+	public static final fun getBoolean (Lhep/dataforge/values/Value;)Z
+	public static final fun getDouble (Lhep/dataforge/values/Value;)D
+	public static final fun getDoubleArray (Lhep/dataforge/values/Value;)[D
+	public static final fun getFloat (Lhep/dataforge/values/Value;)F
+	public static final fun getInt (Lhep/dataforge/values/Value;)I
+	public static final fun getLong (Lhep/dataforge/values/Value;)J
+	public static final fun getShort (Lhep/dataforge/values/Value;)S
+	public static final fun getStringList (Lhep/dataforge/values/Value;)Ljava/util/List;
+	public static final fun isList (Lhep/dataforge/values/Value;)Z
+	public static final fun isNull (Lhep/dataforge/values/Value;)Z
+	public static final fun toMeta (Lhep/dataforge/values/Value;)Lhep/dataforge/meta/MetaBuilder;
+}
+
+public final class hep/dataforge/values/ValueKt {
+	public static final fun asValue (Ljava/lang/Enum;)Lhep/dataforge/values/Value;
+	public static final fun asValue (Ljava/lang/Iterable;)Lhep/dataforge/values/Value;
+	public static final fun asValue (Ljava/lang/Number;)Lhep/dataforge/values/Value;
+	public static final fun asValue (Ljava/lang/String;)Lhep/dataforge/values/Value;
+	public static final fun asValue (Z)Lhep/dataforge/values/Value;
+	public static final fun asValue ([B)Lhep/dataforge/values/Value;
+	public static final fun asValue ([F)Lhep/dataforge/values/Value;
+	public static final fun asValue ([I)Lhep/dataforge/values/Value;
+	public static final fun asValue ([J)Lhep/dataforge/values/Value;
+	public static final fun asValue ([S)Lhep/dataforge/values/Value;
+	public static final fun parseValue (Ljava/lang/String;)Lhep/dataforge/values/Value;
+}
+
+public final class hep/dataforge/values/ValueSerializer : kotlinx/serialization/KSerializer {
+	public static final field INSTANCE Lhep/dataforge/values/ValueSerializer;
+	public fun deserialize (Lkotlinx/serialization/encoding/Decoder;)Lhep/dataforge/values/Value;
+	public synthetic fun deserialize (Lkotlinx/serialization/encoding/Decoder;)Ljava/lang/Object;
+	public fun getDescriptor ()Lkotlinx/serialization/descriptors/SerialDescriptor;
+	public fun serialize (Lkotlinx/serialization/encoding/Encoder;Lhep/dataforge/values/Value;)V
+	public synthetic fun serialize (Lkotlinx/serialization/encoding/Encoder;Ljava/lang/Object;)V
+}
+
+public final class hep/dataforge/values/ValueType : java/lang/Enum {
+	public static final field BOOLEAN Lhep/dataforge/values/ValueType;
+	public static final field Companion Lhep/dataforge/values/ValueType$Companion;
+	public static final field NULL Lhep/dataforge/values/ValueType;
+	public static final field NUMBER Lhep/dataforge/values/ValueType;
+	public static final field STRING Lhep/dataforge/values/ValueType;
+	public static fun valueOf (Ljava/lang/String;)Lhep/dataforge/values/ValueType;
+	public static fun values ()[Lhep/dataforge/values/ValueType;
+}
+
+public final class hep/dataforge/values/ValueType$$serializer : kotlinx/serialization/internal/GeneratedSerializer {
+	public static final field INSTANCE Lhep/dataforge/values/ValueType$$serializer;
+	public fun childSerializers ()[Lkotlinx/serialization/KSerializer;
+	public fun deserialize (Lkotlinx/serialization/encoding/Decoder;)Lhep/dataforge/values/ValueType;
+	public synthetic fun deserialize (Lkotlinx/serialization/encoding/Decoder;)Ljava/lang/Object;
+	public fun getDescriptor ()Lkotlinx/serialization/descriptors/SerialDescriptor;
+	public fun serialize (Lkotlinx/serialization/encoding/Encoder;Lhep/dataforge/values/ValueType;)V
+	public synthetic fun serialize (Lkotlinx/serialization/encoding/Encoder;Ljava/lang/Object;)V
+	public fun typeParametersSerializers ()[Lkotlinx/serialization/KSerializer;
+}
+
+public final class hep/dataforge/values/ValueType$Companion {
+	public final fun serializer ()Lkotlinx/serialization/KSerializer;
+}
+
diff --git a/dataforge-meta/build.gradle.kts b/dataforge-meta/build.gradle.kts
index f19a39fc..980924a7 100644
--- a/dataforge-meta/build.gradle.kts
+++ b/dataforge-meta/build.gradle.kts
@@ -1,9 +1,12 @@
-import scientifik.useSerialization
-
 plugins {
-    id("scientifik.mpp")
+    id("ru.mipt.npm.mpp")
+    id("ru.mipt.npm.native")
 }
 
-useSerialization()
+kscience {
+    useSerialization{
+        json()
+    }
+}
 
 description = "Meta definition and basic operations on meta"
\ No newline at end of file
diff --git a/dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/Config.kt b/dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/Config.kt
index 0ac29d86..2674d0a8 100644
--- a/dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/Config.kt
+++ b/dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/Config.kt
@@ -4,25 +4,30 @@ import hep.dataforge.names.Name
 import hep.dataforge.names.NameToken
 import hep.dataforge.names.asName
 import hep.dataforge.names.plus
-import kotlinx.serialization.*
+import kotlinx.serialization.KSerializer
+import kotlinx.serialization.Serializable
+import kotlinx.serialization.descriptors.SerialDescriptor
+import kotlinx.serialization.encoding.Decoder
+import kotlinx.serialization.encoding.Encoder
+import kotlin.collections.set
 
 //TODO add validator to configuration
 
-data class MetaListener(
+public data class MetaListener(
     val owner: Any? = null,
     val action: (name: Name, oldItem: MetaItem<*>?, newItem: MetaItem<*>?) -> Unit
 )
 
-interface ObservableMeta : Meta {
-    fun onChange(owner: Any?, action: (name: Name, oldItem: MetaItem<*>?, newItem: MetaItem<*>?) -> Unit)
-    fun removeListener(owner: Any?)
+public interface ObservableMeta : Meta {
+    public fun onChange(owner: Any?, action: (name: Name, oldItem: MetaItem<*>?, newItem: MetaItem<*>?) -> Unit)
+    public fun removeListener(owner: Any?)
 }
 
 /**
  * Mutable meta representing object state
  */
-@Serializable
-class Config : AbstractMutableMeta<Config>(), ObservableMeta {
+@Serializable(Config.Companion::class)
+public class Config() : AbstractMutableMeta<Config>(), ObservableMeta {
 
     private val listeners = HashSet<MetaListener>()
 
@@ -46,12 +51,12 @@ class Config : AbstractMutableMeta<Config>(), ObservableMeta {
 
     override fun replaceItem(key: NameToken, oldItem: MetaItem<Config>?, newItem: MetaItem<Config>?) {
         if (newItem == null) {
-            _items.remove(key)
+            children.remove(key)
             if (oldItem != null && oldItem is MetaItem.NodeItem<Config>) {
                 oldItem.node.removeListener(this)
             }
         } else {
-            _items[key] = newItem
+            children[key] = newItem
             if (newItem is MetaItem.NodeItem) {
                 newItem.node.onChange(this) { name, oldChild, newChild ->
                     itemChanged(key + name, oldChild, newChild)
@@ -68,10 +73,9 @@ class Config : AbstractMutableMeta<Config>(), ObservableMeta {
 
     override fun empty(): Config = Config()
 
-    @Serializer(Config::class)
-    companion object ConfigSerializer : KSerializer<Config> {
+    public companion object ConfigSerializer : KSerializer<Config> {
 
-        fun empty(): Config = Config()
+        public fun empty(): Config = Config()
         override val descriptor: SerialDescriptor get() = MetaSerializer.descriptor
 
         override fun deserialize(decoder: Decoder): Config {
@@ -84,9 +88,9 @@ class Config : AbstractMutableMeta<Config>(), ObservableMeta {
     }
 }
 
-operator fun Config.get(token: NameToken): MetaItem<Config>? = items[token]
+public operator fun Config.get(token: NameToken): MetaItem<Config>? = items[token]
 
-fun Meta.asConfig(): Config = this as? Config ?: Config().also { builder ->
+public fun Meta.asConfig(): Config = this as? Config ?: Config().also { builder ->
     this.items.mapValues { entry ->
         val item = entry.value
         builder[entry.key.asName()] = when (item) {
diff --git a/dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/Configurable.kt b/dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/Configurable.kt
index 794292b9..764ee1ea 100644
--- a/dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/Configurable.kt
+++ b/dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/Configurable.kt
@@ -1,115 +1,24 @@
 package hep.dataforge.meta
 
-import hep.dataforge.meta.descriptors.*
 import hep.dataforge.names.Name
-import hep.dataforge.names.asName
-import hep.dataforge.names.toName
-import hep.dataforge.values.Value
 import kotlin.properties.ReadWriteProperty
-import kotlin.reflect.KProperty
 
 /**
- * A container that holds a [Config] and a default item provider.
- * Default item provider could be use for example to reference parent configuration.
- * It is not possible to know if some property is declared by provider just by looking on [Configurable],
- * this information should be provided externally.
+ * A container that holds a [Config].
  */
-interface Configurable : Described, MutableItemProvider {
+public interface Configurable {
     /**
      * Backing config
      */
-    val config: Config
-
-    /**
-     * Default meta item provider
-     */
-    fun getDefaultItem(name: Name): MetaItem<*>? = null
-
-    /**
-     * Check if property with given [name] could be assigned to [value]
-     */
-    fun validateItem(name: Name, item: MetaItem<*>?): Boolean {
-        val descriptor = descriptor?.get(name)
-        return descriptor?.validateItem(item) ?: true
-    }
-
-    override val descriptor: NodeDescriptor? get() = null
-
-    /**
-     * Get a property with default
-     */
-    override fun getItem(name: Name): MetaItem<*>? =
-        config[name] ?: getDefaultItem(name) ?: descriptor?.get(name)?.defaultItem()
-
-    /**
-     * Set a configurable property
-     */
-    override fun setItem(name: Name, item: MetaItem<*>?) {
-        if (validateItem(name, item)) {
-            config.setItem(name, item)
-        } else {
-            error("Validation failed for property $name with value $item")
-        }
-    }
+    public val config: Config
 }
 
-/**
- * Reset the property to its default value
- */
-fun Configurable.resetProperty(name: Name) {
-    setItem(name, null)
-}
 
-fun Configurable.getItem(key: String) = getItem(key.toName())
-
-fun Configurable.setItem(name: Name, value: Value?) = setItem(name, value?.let { MetaItem.ValueItem(value) })
-fun Configurable.setItem(name: Name, meta: Meta?) = setItem(name, meta?.let { MetaItem.NodeItem(meta) })
-
-fun Configurable.setItem(key: String, item: MetaItem<*>?) = setItem(key.toName(), item)
-
-fun Configurable.setItem(key: String, value: Value?) = setItem(key, value?.let { MetaItem.ValueItem(value) })
-fun Configurable.setItem(key: String, meta: Meta?) = setItem(key, meta?.let { MetaItem.NodeItem(meta) })
-
-fun <T : Configurable> T.configure(meta: Meta): T = this.apply { config.update(meta) }
+public fun <T : Configurable> T.configure(meta: Meta): T = this.apply { config.update(meta) }
 
 @DFBuilder
-inline fun <T : Configurable> T.configure(action: Config.() -> Unit): T = apply { config.apply(action) }
+public inline fun <T : Configurable> T.configure(action: Config.() -> Unit): T = apply { config.apply(action) }
 
 /* Node delegates */
 
-fun Configurable.config(key: Name? = null): ReadWriteProperty<Any?, Config?> =
-    config.node(key)
-
-fun MutableItemProvider.node(key: Name? = null): ReadWriteProperty<Any?, Meta?> = item(key).convert(
-    reader = { it.node },
-    writer = { it?.let { MetaItem.NodeItem(it) } }
-)
-
-fun <T : Configurable> Configurable.spec(
-    spec: Specification<T>, key: Name? = null
-): ReadWriteProperty<Any?, T?> = object : ReadWriteProperty<Any?, T?> {
-    override fun getValue(thisRef: Any?, property: KProperty<*>): T? {
-        val name = key ?: property.name.asName()
-        return config[name].node?.let { spec.wrap(it) }
-    }
-
-    override fun setValue(thisRef: Any?, property: KProperty<*>, value: T?) {
-        val name = key ?: property.name.asName()
-        config[name] = value?.config
-    }
-}
-
-fun <T : Configurable> Configurable.spec(
-    spec: Specification<T>, default: T, key: Name? = null
-): ReadWriteProperty<Any?, T> = object : ReadWriteProperty<Any?, T> {
-    override fun getValue(thisRef: Any?, property: KProperty<*>): T {
-        val name = key ?: property.name.asName()
-        return config[name].node?.let { spec.wrap(it) } ?: default
-    }
-
-    override fun setValue(thisRef: Any?, property: KProperty<*>, value: T) {
-        val name = key ?: property.name.asName()
-        config[name] = value.config
-    }
-}
-
+public fun Configurable.config(key: Name? = null): ReadWriteProperty<Any?, Config?> = config.node(key)
diff --git a/dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/ItemDelegate.kt b/dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/ItemDelegate.kt
index aa2dec23..eab2573f 100644
--- a/dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/ItemDelegate.kt
+++ b/dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/ItemDelegate.kt
@@ -5,62 +5,107 @@ import hep.dataforge.names.Name
 import hep.dataforge.names.asName
 import hep.dataforge.values.Value
 import kotlin.properties.ReadOnlyProperty
-import kotlin.reflect.KProperty
 
 /* Meta delegates */
 
-open class ItemDelegate(
-    open val owner: ItemProvider,
-    val key: Name? = null,
-    open val default: MetaItem<*>? = null
-) : ReadOnlyProperty<Any?, MetaItem<*>?> {
-    override fun getValue(thisRef: Any?, property: KProperty<*>): MetaItem<*>? {
-        return owner.getItem(key ?: property.name.asName()) ?: default
-    }
-}
+public typealias ItemDelegate = ReadOnlyProperty<Any?, MetaItem<*>?>
 
-fun ItemProvider.item(key: Name? = null): ItemDelegate = ItemDelegate(this, key)
+public fun ItemProvider.item(key: Name? = null): ItemDelegate = ReadOnlyProperty { _, property ->
+    getItem(key ?: property.name.asName())
+}
 
 //TODO add caching for sealed nodes
 
 
-//Read-only delegates for Metas
+/**
+ * Apply a converter to this delegate creating a delegate with a custom type
+ */
+public fun <R : Any> ItemDelegate.convert(
+    converter: MetaConverter<R>,
+): ReadOnlyProperty<Any?, R?> = ReadOnlyProperty { thisRef, property ->
+    this@convert.getValue(thisRef, property)?.let(converter::itemToObject)
+}
+
+/*
+ *
+ */
+public fun <R : Any> ItemDelegate.convert(
+    converter: MetaConverter<R>,
+    default: () -> R,
+): ReadOnlyProperty<Any?, R> = ReadOnlyProperty<Any?, R> { thisRef, property ->
+    this@convert.getValue(thisRef, property)?.let(converter::itemToObject) ?: default()
+}
+
+/**
+ * A converter with a custom reader transformation
+ */
+public fun <R> ItemDelegate.convert(
+    reader: (MetaItem<*>?) -> R,
+): ReadOnlyProperty<Any?, R> = ReadOnlyProperty<Any?, R> { thisRef, property ->
+    this@convert.getValue(thisRef, property).let(reader)
+}
+
+/* Read-only delegates for [ItemProvider] */
 
 /**
  * A property delegate that uses custom key
  */
-fun ItemProvider.value(key: Name? = null): ReadOnlyProperty<Any?, Value?> =
+public fun ItemProvider.value(key: Name? = null): ReadOnlyProperty<Any?, Value?> =
     item(key).convert(MetaConverter.value)
 
-fun ItemProvider.string(key: Name? = null): ReadOnlyProperty<Any?, String?> =
+public fun ItemProvider.string(key: Name? = null): ReadOnlyProperty<Any?, String?> =
     item(key).convert(MetaConverter.string)
 
-fun ItemProvider.boolean(key: Name? = null): ReadOnlyProperty<Any?, Boolean?> =
+public fun ItemProvider.boolean(key: Name? = null): ReadOnlyProperty<Any?, Boolean?> =
     item(key).convert(MetaConverter.boolean)
 
-fun ItemProvider.number(key: Name? = null): ReadOnlyProperty<Any?, Number?> =
+public fun ItemProvider.number(key: Name? = null): ReadOnlyProperty<Any?, Number?> =
     item(key).convert(MetaConverter.number)
 
-fun ItemProvider.node(key: Name? = null): ReadOnlyProperty<Any?, Meta?> =
+public fun ItemProvider.double(key: Name? = null): ReadOnlyProperty<Any?, Double?> =
+    item(key).convert(MetaConverter.double)
+
+public fun ItemProvider.float(key: Name? = null): ReadOnlyProperty<Any?, Float?> =
+    item(key).convert(MetaConverter.float)
+
+public fun ItemProvider.int(key: Name? = null): ReadOnlyProperty<Any?, Int?> =
+    item(key).convert(MetaConverter.int)
+
+public fun ItemProvider.long(key: Name? = null): ReadOnlyProperty<Any?, Long?> =
+    item(key).convert(MetaConverter.long)
+
+public fun ItemProvider.node(key: Name? = null): ReadOnlyProperty<Any?, Meta?> =
     item(key).convert(MetaConverter.meta)
 
-fun ItemProvider.string(default: String, key: Name? = null): ReadOnlyProperty<Any?, String> =
+public fun ItemProvider.string(default: String, key: Name? = null): ReadOnlyProperty<Any?, String> =
     item(key).convert(MetaConverter.string) { default }
 
-fun ItemProvider.boolean(default: Boolean, key: Name? = null): ReadOnlyProperty<Any?, Boolean> =
+public fun ItemProvider.boolean(default: Boolean, key: Name? = null): ReadOnlyProperty<Any?, Boolean> =
     item(key).convert(MetaConverter.boolean) { default }
 
-fun ItemProvider.number(default: Number, key: Name? = null): ReadOnlyProperty<Any?, Number> =
+public fun ItemProvider.number(default: Number, key: Name? = null): ReadOnlyProperty<Any?, Number> =
     item(key).convert(MetaConverter.number) { default }
 
-inline fun <reified E : Enum<E>> ItemProvider.enum(default: E, key: Name? = null): ReadOnlyProperty<Any?, E> =
+public fun ItemProvider.double(default: Double, key: Name? = null): ReadOnlyProperty<Any?, Double> =
+    item(key).convert(MetaConverter.double) { default }
+
+public fun ItemProvider.float(default: Float, key: Name? = null): ReadOnlyProperty<Any?, Float> =
+    item(key).convert(MetaConverter.float) { default }
+
+public fun ItemProvider.int(default: Int, key: Name? = null): ReadOnlyProperty<Any?, Int> =
+    item(key).convert(MetaConverter.int) { default }
+
+public fun ItemProvider.long(default: Long, key: Name? = null): ReadOnlyProperty<Any?, Long> =
+    item(key).convert(MetaConverter.long) { default }
+
+public inline fun <reified E : Enum<E>> ItemProvider.enum(default: E, key: Name? = null): ReadOnlyProperty<Any?, E> =
     item(key).convert(MetaConverter.enum()) { default }
 
-fun ItemProvider.string(key: Name? = null, default: () -> String): ReadOnlyProperty<Any?, String> =
+public fun ItemProvider.string(key: Name? = null, default: () -> String): ReadOnlyProperty<Any?, String> =
     item(key).convert(MetaConverter.string, default)
 
-fun ItemProvider.boolean(key: Name? = null, default: () -> Boolean): ReadOnlyProperty<Any?, Boolean> =
+public fun ItemProvider.boolean(key: Name? = null, default: () -> Boolean): ReadOnlyProperty<Any?, Boolean> =
     item(key).convert(MetaConverter.boolean, default)
 
-fun ItemProvider.number(key: Name? = null, default: () -> Number): ReadOnlyProperty<Any?, Number> =
+public fun ItemProvider.number(key: Name? = null, default: () -> Number): ReadOnlyProperty<Any?, Number> =
     item(key).convert(MetaConverter.number, default)
diff --git a/dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/JsonMeta.kt b/dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/JsonMeta.kt
index 221b040d..2cabc8f1 100644
--- a/dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/JsonMeta.kt
+++ b/dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/JsonMeta.kt
@@ -4,6 +4,7 @@ package hep.dataforge.meta
 
 import hep.dataforge.meta.JsonMeta.Companion.JSON_ARRAY_KEY
 import hep.dataforge.meta.descriptors.ItemDescriptor
+import hep.dataforge.meta.descriptors.ItemDescriptor.Companion.DEFAULT_INDEX_KEY
 import hep.dataforge.meta.descriptors.NodeDescriptor
 import hep.dataforge.meta.descriptors.ValueDescriptor
 import hep.dataforge.names.NameToken
@@ -15,7 +16,7 @@ import kotlinx.serialization.json.*
 /**
  * @param descriptor reserved for custom serialization in future
  */
-fun Value.toJson(descriptor: ValueDescriptor? = null): JsonElement {
+public fun Value.toJson(descriptor: ValueDescriptor? = null): JsonElement {
     return if (isList()) {
         JsonArray(list.map { it.toJson() })
     } else {
@@ -52,7 +53,7 @@ private fun Meta.toJsonWithIndex(descriptor: NodeDescriptor?, indexValue: String
     fun addElement(key: String) {
         val itemDescriptor = descriptor?.items?.get(key)
         val jsonKey = key.toJsonKey(itemDescriptor)
-        val items: Map<String, MetaItem<*>> = getIndexed(key)
+        val items: Map<String?, MetaItem<*>> = getIndexed(key)
         when (items.size) {
             0 -> {
                 //do nothing
@@ -61,9 +62,9 @@ private fun Meta.toJsonWithIndex(descriptor: NodeDescriptor?, indexValue: String
                 elementMap[jsonKey] = items.values.first().toJsonElement(itemDescriptor, null)
             }
             else -> {
-                val array = jsonArray {
+                val array = buildJsonArray {
                     items.forEach { (index, item) ->
-                        +item.toJsonElement(itemDescriptor, index)
+                        add(item.toJsonElement(itemDescriptor, index))
                     }
                 }
                 elementMap[jsonKey] = array
@@ -75,32 +76,31 @@ private fun Meta.toJsonWithIndex(descriptor: NodeDescriptor?, indexValue: String
 
 
     if (indexValue != null) {
-        val indexKey = descriptor?.indexKey ?: NodeDescriptor.DEFAULT_INDEX_KEY
+        val indexKey = descriptor?.indexKey ?: DEFAULT_INDEX_KEY
         elementMap[indexKey] = JsonPrimitive(indexValue)
     }
 
     return JsonObject(elementMap)
 }
 
-fun Meta.toJson(descriptor: NodeDescriptor? = null): JsonObject = toJsonWithIndex(descriptor, null)
+public fun Meta.toJson(descriptor: NodeDescriptor? = null): JsonObject = toJsonWithIndex(descriptor, null)
 
-fun JsonObject.toMeta(descriptor: NodeDescriptor? = null): JsonMeta = JsonMeta(this, descriptor)
+public fun JsonObject.toMeta(descriptor: NodeDescriptor? = null): JsonMeta = JsonMeta(this, descriptor)
 
-fun JsonPrimitive.toValue(descriptor: ValueDescriptor?): Value {
+public fun JsonPrimitive.toValue(descriptor: ValueDescriptor?): Value {
     return when (this) {
         JsonNull -> Null
-        is JsonLiteral -> {
-            when (body) {
-                true -> True
-                false -> False
-                is Number -> NumberValue(body as Number)
-                else -> StringValue(content)
+        else -> {
+            if (isString) {
+                StringValue(content)
+            } else {
+                content.parseValue()
             }
         }
     }
 }
 
-fun JsonElement.toMetaItem(descriptor: ItemDescriptor? = null): MetaItem<JsonMeta> = when (this) {
+public fun JsonElement.toMetaItem(descriptor: ItemDescriptor? = null): MetaItem<JsonMeta> = when (this) {
     is JsonPrimitive -> {
         val value = this.toValue(descriptor as? ValueDescriptor)
         MetaItem.ValueItem(value)
@@ -122,7 +122,7 @@ fun JsonElement.toMetaItem(descriptor: ItemDescriptor? = null): MetaItem<JsonMet
             MetaItem.ValueItem(value)
         } else {
             //We can't return multiple items therefore we create top level node
-            json { JSON_ARRAY_KEY to this@toMetaItem }.toMetaItem(descriptor)
+            buildJsonObject { put(JSON_ARRAY_KEY, this@toMetaItem) }.toMetaItem(descriptor)
         }
     }
 }
@@ -130,7 +130,7 @@ fun JsonElement.toMetaItem(descriptor: ItemDescriptor? = null): MetaItem<JsonMet
 /**
  * A meta wrapping json object
  */
-class JsonMeta(val json: JsonObject, val descriptor: NodeDescriptor? = null) : MetaBase() {
+public class JsonMeta(private val json: JsonObject, private val descriptor: NodeDescriptor? = null) : MetaBase() {
 
     private fun buildItems(): Map<NameToken, MetaItem<JsonMeta>> {
         val map = LinkedHashMap<NameToken, MetaItem<JsonMeta>>()
@@ -159,9 +159,9 @@ class JsonMeta(val json: JsonObject, val descriptor: NodeDescriptor? = null) : M
                     )
                     map[key] = MetaItem.ValueItem(listValue)
                 } else value.forEachIndexed { index, jsonElement ->
-                    val indexKey = (itemDescriptor as? NodeDescriptor)?.indexKey ?: NodeDescriptor.DEFAULT_INDEX_KEY
+                    val indexKey = (itemDescriptor as? NodeDescriptor)?.indexKey ?: DEFAULT_INDEX_KEY
                     val indexValue: String = (jsonElement as? JsonObject)
-                        ?.get(indexKey)?.contentOrNull
+                        ?.get(indexKey)?.jsonPrimitive?.contentOrNull
                         ?: index.toString() //In case index is non-string, the backward transformation will be broken.
 
                     val token = key.withIndex(indexValue)
@@ -174,10 +174,10 @@ class JsonMeta(val json: JsonObject, val descriptor: NodeDescriptor? = null) : M
 
     override val items: Map<NameToken, MetaItem<JsonMeta>> by lazy(::buildItems)
 
-    companion object{
+    public companion object {
         /**
          * A key representing top-level json array of nodes, which could not be directly represented by a meta node
          */
-        const val JSON_ARRAY_KEY = "@jsonArray"
+        public const val JSON_ARRAY_KEY: String = "@jsonArray"
     }
 }
\ No newline at end of file
diff --git a/dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/Laminate.kt b/dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/Laminate.kt
index 7dec0790..5545358c 100644
--- a/dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/Laminate.kt
+++ b/dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/Laminate.kt
@@ -7,9 +7,9 @@ import hep.dataforge.names.NameToken
  * A meta laminate consisting of multiple immutable meta layers. For mutable front layer, use [Scheme].
  * If [layers] list contains a [Laminate] it is flat-mapped.
  */
-class Laminate(layers: List<Meta>) : MetaBase() {
+public class Laminate(layers: List<Meta>) : MetaBase() {
 
-    val layers: List<Meta> = layers.flatMap {
+    public val layers: List<Meta> = layers.flatMap {
         if (it is Laminate) {
             it.layers
         } else {
@@ -17,8 +17,6 @@ class Laminate(layers: List<Meta>) : MetaBase() {
         }
     }
 
-    constructor(vararg layers: Meta?) : this(layers.filterNotNull())
-
     override val items: Map<NameToken, MetaItem<Meta>> by lazy {
         layers.map { it.items.keys }.flatten().associateWith { key ->
             layers.asSequence().map { it.items[key] }.filterNotNull().let(replaceRule)
@@ -28,21 +26,21 @@ class Laminate(layers: List<Meta>) : MetaBase() {
     /**
      * Generate sealed meta using [mergeRule]
      */
-    fun merge(): SealedMeta {
+    public fun merge(): SealedMeta {
         val items = layers.map { it.items.keys }.flatten().associateWith { key ->
             layers.asSequence().map { it.items[key] }.filterNotNull().merge()
         }
         return SealedMeta(items)
     }
 
-    companion object {
+    public companion object {
 
         /**
          * The default rule which always uses the first found item in sequence alongside with its children.
          *
          * TODO add picture
          */
-        val replaceRule: (Sequence<MetaItem<*>>) -> MetaItem<SealedMeta> = { it.first().seal() }
+        public val replaceRule: (Sequence<MetaItem<*>>) -> MetaItem<SealedMeta> = { it.first().seal() }
 
         private fun Sequence<MetaItem<*>>.merge(): MetaItem<SealedMeta> {
             return when {
@@ -76,14 +74,17 @@ class Laminate(layers: List<Meta>) : MetaBase() {
          * The values a replaced but meta children are joined
          * TODO add picture
          */
-        val mergeRule: (Sequence<MetaItem<*>>) -> MetaItem<SealedMeta> = { it.merge() }
+        public val mergeRule: (Sequence<MetaItem<*>>) -> MetaItem<SealedMeta> = { it.merge() }
     }
 }
 
+@Suppress("FunctionName")
+public fun Laminate(vararg layers: Meta?): Laminate = Laminate(layers.filterNotNull())
+
 /**
  * Performance optimized version of get method
  */
-fun Laminate.getFirst(name: Name): MetaItem<*>? {
+public fun Laminate.getFirst(name: Name): MetaItem<*>? {
     layers.forEach { layer ->
         layer[name]?.let { return it }
     }
@@ -93,11 +94,11 @@ fun Laminate.getFirst(name: Name): MetaItem<*>? {
 /**
  * Create a new [Laminate] adding given layer to the top
  */
-fun Laminate.withTop(meta: Meta): Laminate = Laminate(listOf(meta) + layers)
+public fun Laminate.withTop(meta: Meta): Laminate = Laminate(listOf(meta) + layers)
 
 /**
  * Create a new [Laminate] adding given layer to the bottom
  */
-fun Laminate.withBottom(meta: Meta): Laminate = Laminate(layers + meta)
+public fun Laminate.withBottom(meta: Meta): Laminate = Laminate(layers + meta)
 
 //TODO add custom rules for Laminate merge
diff --git a/dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/Meta.kt b/dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/Meta.kt
index a89d79c9..c8ed6755 100644
--- a/dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/Meta.kt
+++ b/dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/Meta.kt
@@ -4,8 +4,12 @@ import hep.dataforge.meta.Meta.Companion.VALUE_KEY
 import hep.dataforge.meta.MetaItem.NodeItem
 import hep.dataforge.meta.MetaItem.ValueItem
 import hep.dataforge.names.*
-import hep.dataforge.values.*
-import kotlinx.serialization.*
+import hep.dataforge.values.EnumValue
+import hep.dataforge.values.Null
+import hep.dataforge.values.Value
+import hep.dataforge.values.boolean
+import kotlinx.serialization.Serializable
+import kotlinx.serialization.json.Json
 
 
 /**
@@ -13,28 +17,17 @@ import kotlinx.serialization.*
  * * a [ValueItem] (leaf)
  * * a [NodeItem] (node)
  */
-@Serializable
-sealed class MetaItem<out M : Meta> {
+@Serializable(MetaItemSerializer::class)
+public sealed class MetaItem<out M : Meta>() {
 
     abstract override fun equals(other: Any?): Boolean
 
     abstract override fun hashCode(): Int
 
-    @Serializable
-    class ValueItem(val value: Value) : MetaItem<Nothing>() {
+    @Serializable(MetaItemSerializer::class)
+    public class ValueItem(public val value: Value) : MetaItem<Nothing>() {
         override fun toString(): String = value.toString()
 
-        @Serializer(ValueItem::class)
-        companion object : KSerializer<ValueItem> {
-            override val descriptor: SerialDescriptor get() = ValueSerializer.descriptor
-
-            override fun deserialize(decoder: Decoder): ValueItem = ValueItem(ValueSerializer.deserialize(decoder))
-
-            override fun serialize(encoder: Encoder, value: ValueItem) {
-                ValueSerializer.serialize(encoder, value.value)
-            }
-        }
-
         override fun equals(other: Any?): Boolean {
             return this.value == (other as? ValueItem)?.value
         }
@@ -44,29 +37,18 @@ sealed class MetaItem<out M : Meta> {
         }
     }
 
-    @Serializable
-    class NodeItem<M : Meta>(@Serializable(MetaSerializer::class) val node: M) : MetaItem<M>() {
+    @Serializable(MetaItemSerializer::class)
+    public class NodeItem<M : Meta>(public val node: M) : MetaItem<M>() {
         //Fixing serializer for node could cause class cast problems, but it should not since Meta descendants are not serializeable
         override fun toString(): String = node.toString()
 
-        @Serializer(NodeItem::class)
-        companion object : KSerializer<NodeItem<out Meta>> {
-            override val descriptor: SerialDescriptor get() = MetaSerializer.descriptor
-
-            override fun deserialize(decoder: Decoder): NodeItem<*> = NodeItem(MetaSerializer.deserialize(decoder))
-
-            override fun serialize(encoder: Encoder, value: NodeItem<*>) {
-                MetaSerializer.serialize(encoder, value.node)
-            }
-        }
-
         override fun equals(other: Any?): Boolean = node == (other as? NodeItem<*>)?.node
 
         override fun hashCode(): Int = node.hashCode()
     }
 
-    companion object {
-        fun of(arg: Any?): MetaItem<*> {
+    public companion object {
+        public fun of(arg: Any?): MetaItem<*> {
             return when (arg) {
                 null -> ValueItem(Null)
                 is MetaItem<*> -> arg
@@ -77,16 +59,24 @@ sealed class MetaItem<out M : Meta> {
     }
 }
 
+public fun Value.asMetaItem(): ValueItem = ValueItem(this)
+public fun <M : Meta> M.asMetaItem(): NodeItem<M> = NodeItem(this)
+
 /**
  * The object that could be represented as [Meta]. Meta provided by [toMeta] method should fully represent object state.
  * Meaning that two states with the same meta are equal.
  */
-interface MetaRepr {
-    fun toMeta(): Meta
+@Serializable(MetaSerializer::class)
+public interface MetaRepr {
+    public fun toMeta(): Meta
 }
 
-interface ItemProvider{
-    fun getItem(name: Name): MetaItem<*>?
+public fun interface ItemProvider {
+    public fun getItem(name: Name): MetaItem<*>?
+
+    public companion object {
+        public val EMPTY: ItemProvider = ItemProvider { null }
+    }
 }
 
 /**
@@ -96,15 +86,15 @@ interface ItemProvider{
  *
  *   * Same name siblings are supported via elements with the same [Name] but different queries
  */
-interface Meta : MetaRepr, ItemProvider {
+public interface Meta : MetaRepr, ItemProvider {
     /**
      * Top level items of meta tree
      */
-    val items: Map<NameToken, MetaItem<*>>
+    public val items: Map<NameToken, MetaItem<*>>
 
     override fun getItem(name: Name): MetaItem<*>? {
         if (name.isEmpty()) return NodeItem(this)
-        return name.first()?.let { token ->
+        return name.firstOrNull()?.let { token ->
             val tail = name.cutFirst()
             when (tail.length) {
                 0 -> items[token]
@@ -121,15 +111,15 @@ interface Meta : MetaRepr, ItemProvider {
 
     override fun toString(): String
 
-    companion object {
-        const val TYPE = "meta"
+    public companion object {
+        public const val TYPE: String = "meta"
 
         /**
          * A key for single value node
          */
-        const val VALUE_KEY = "@value"
+        public const val VALUE_KEY: String = "@value"
 
-        val EMPTY: Meta = object: MetaBase() {
+        public val EMPTY: Meta = object : MetaBase() {
             override val items: Map<NameToken, MetaItem<*>> = emptyMap()
         }
     }
@@ -142,19 +132,19 @@ interface Meta : MetaRepr, ItemProvider {
  *
  * If [name] is empty return current [Meta] as a [NodeItem]
  */
-operator fun Meta?.get(name: Name): MetaItem<*>? = this?.getItem(name)
+public operator fun Meta?.get(name: Name): MetaItem<*>? = this?.getItem(name)
 
-operator fun Meta?.get(token: NameToken): MetaItem<*>? = this?.items?.get(token)
+public operator fun Meta?.get(token: NameToken): MetaItem<*>? = this?.items?.get(token)
 
 /**
  * Parse [Name] from [key] using full name notation and pass it to [Meta.get]
  */
-operator fun Meta?.get(key: String): MetaItem<*>? = get(key.toName())
+public operator fun Meta?.get(key: String): MetaItem<*>? = get(key.toName())
 
 /**
  * Get a sequence of [Name]-[Value] pairs
  */
-fun Meta.values(): Sequence<Pair<Name, Value>> {
+public fun Meta.values(): Sequence<Pair<Name, Value>> {
     return items.asSequence().flatMap { (key, item) ->
         when (item) {
             is ValueItem -> sequenceOf(key.asName() to item.value)
@@ -166,7 +156,7 @@ fun Meta.values(): Sequence<Pair<Name, Value>> {
 /**
  * Get a sequence of all [Name]-[MetaItem] pairs for all items including nodes
  */
-fun Meta.sequence(): Sequence<Pair<Name, MetaItem<*>>> {
+public fun Meta.sequence(): Sequence<Pair<Name, MetaItem<*>>> {
     return sequence {
         items.forEach { (key, item) ->
             yield(key.asName() to item)
@@ -179,33 +169,33 @@ fun Meta.sequence(): Sequence<Pair<Name, MetaItem<*>>> {
     }
 }
 
-operator fun Meta.iterator(): Iterator<Pair<Name, MetaItem<*>>> = sequence().iterator()
+public operator fun Meta.iterator(): Iterator<Pair<Name, MetaItem<*>>> = sequence().iterator()
 
 /**
  * A meta node that ensures that all of its descendants has at least the same type
  */
-interface MetaNode<out M : MetaNode<M>> : Meta {
+public interface MetaNode<out M : MetaNode<M>> : Meta {
     override val items: Map<NameToken, MetaItem<M>>
 }
 
 /**
  * The same as [Meta.get], but with specific node type
  */
-operator fun <M : MetaNode<M>> M?.get(name: Name): MetaItem<M>? = if( this == null) {
+public operator fun <M : MetaNode<M>> M?.get(name: Name): MetaItem<M>? = if (this == null) {
     null
 } else {
     @Suppress("UNCHECKED_CAST", "ReplaceGetOrSet")
     (this as Meta).get(name) as MetaItem<M>? // Do not change
 }
 
-operator fun <M : MetaNode<M>> M?.get(key: String): MetaItem<M>? = this[key.toName()]
+public operator fun <M : MetaNode<M>> M?.get(key: String): MetaItem<M>? = this[key.toName()]
 
-operator fun <M : MetaNode<M>> M?.get(key: NameToken): MetaItem<M>? = this[key.asName()]
+public operator fun <M : MetaNode<M>> M?.get(key: NameToken): MetaItem<M>? = this[key.asName()]
 
 /**
  * Equals, hashcode and to string for any meta
  */
-abstract class MetaBase : Meta {
+public abstract class MetaBase : Meta {
 
     override fun equals(other: Any?): Boolean = if (other is Meta) {
         this.items == other.items
@@ -215,30 +205,33 @@ abstract class MetaBase : Meta {
 
     override fun hashCode(): Int = items.hashCode()
 
-    override fun toString(): String = JSON_PRETTY.stringify(MetaSerializer, this)
+    override fun toString(): String = Json {
+        prettyPrint = true
+        useArrayPolymorphism = true
+    }.encodeToString(MetaSerializer, this)
 }
 
 /**
  * Equals and hash code implementation for meta node
  */
-abstract class AbstractMetaNode<M : MetaNode<M>> : MetaNode<M>, MetaBase()
+public abstract class AbstractMetaNode<M : MetaNode<M>> : MetaNode<M>, MetaBase()
 
 /**
  * The meta implementation which is guaranteed to be immutable.
  *
  * If the argument is possibly mutable node, it is copied on creation
  */
-class SealedMeta internal constructor(
-    override val items: Map<NameToken, MetaItem<SealedMeta>>
+public class SealedMeta internal constructor(
+    override val items: Map<NameToken, MetaItem<SealedMeta>>,
 ) : AbstractMetaNode<SealedMeta>()
 
 /**
  * Generate sealed node from [this]. If it is already sealed return it as is
  */
-fun Meta.seal(): SealedMeta = this as? SealedMeta ?: SealedMeta(items.mapValues { entry -> entry.value.seal() })
+public fun Meta.seal(): SealedMeta = this as? SealedMeta ?: SealedMeta(items.mapValues { entry -> entry.value.seal() })
 
 @Suppress("UNCHECKED_CAST")
-fun MetaItem<*>.seal(): MetaItem<SealedMeta> = when (this) {
+public fun MetaItem<*>.seal(): MetaItem<SealedMeta> = when (this) {
     is ValueItem -> this
     is NodeItem -> NodeItem(node.seal())
 }
@@ -246,32 +239,32 @@ fun MetaItem<*>.seal(): MetaItem<SealedMeta> = when (this) {
 /**
  * Unsafe methods to access values and nodes directly from [MetaItem]
  */
-val MetaItem<*>?.value: Value?
+public val MetaItem<*>?.value: Value?
     get() = (this as? ValueItem)?.value
         ?: (this?.node?.get(VALUE_KEY) as? ValueItem)?.value
 
-val MetaItem<*>?.string get() = value?.string
-val MetaItem<*>?.boolean get() = value?.boolean
-val MetaItem<*>?.number get() = value?.number
-val MetaItem<*>?.double get() = number?.toDouble()
-val MetaItem<*>?.float get() = number?.toFloat()
-val MetaItem<*>?.int get() = number?.toInt()
-val MetaItem<*>?.long get() = number?.toLong()
-val MetaItem<*>?.short get() = number?.toShort()
+public val MetaItem<*>?.string: String? get() = value?.string
+public val MetaItem<*>?.boolean: Boolean? get() = value?.boolean
+public val MetaItem<*>?.number: Number? get() = value?.number
+public val MetaItem<*>?.double: Double? get() = number?.toDouble()
+public val MetaItem<*>?.float: Float? get() = number?.toFloat()
+public val MetaItem<*>?.int: Int? get() = number?.toInt()
+public val MetaItem<*>?.long: Long? get() = number?.toLong()
+public val MetaItem<*>?.short: Short? get() = number?.toShort()
 
-inline fun <reified E : Enum<E>> MetaItem<*>?.enum(): E? = if (this is ValueItem && this.value is EnumValue<*>) {
+public inline fun <reified E : Enum<E>> MetaItem<*>?.enum(): E? = if (this is ValueItem && this.value is EnumValue<*>) {
     this.value.value as E
 } else {
     string?.let { enumValueOf<E>(it) }
 }
 
-val MetaItem<*>?.stringList get() = value?.list?.map { it.string } ?: emptyList()
+public val MetaItem<*>.stringList: List<String>? get() = value?.list?.map { it.string }
 
-val <M : Meta> MetaItem<M>?.node: M?
+public val <M : Meta> MetaItem<M>?.node: M?
     get() = when (this) {
         null -> null
         is ValueItem -> null//error("Trying to interpret value meta item as node item")
         is NodeItem -> node
     }
 
-fun Meta.isEmpty() = this === Meta.EMPTY || this.items.isEmpty()
\ No newline at end of file
+public fun Meta.isEmpty(): Boolean = this === Meta.EMPTY || this.items.isEmpty()
\ No newline at end of file
diff --git a/dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/MetaBuilder.kt b/dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/MetaBuilder.kt
index da1bafad..cd041275 100644
--- a/dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/MetaBuilder.kt
+++ b/dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/MetaBuilder.kt
@@ -11,113 +11,109 @@ import kotlin.jvm.JvmName
  * DSL builder for meta. Is not intended to store mutable state
  */
 @DFBuilder
-class MetaBuilder : AbstractMutableMeta<MetaBuilder>() {
+public class MetaBuilder : AbstractMutableMeta<MetaBuilder>() {
     override fun wrapNode(meta: Meta): MetaBuilder = if (meta is MetaBuilder) meta else meta.builder()
     override fun empty(): MetaBuilder = MetaBuilder()
 
-    infix fun String.put(item: MetaItem<*>?) {
+    public infix fun String.put(item: MetaItem<*>?) {
         set(this, item)
     }
 
-    infix fun String.put(value: Value?) {
+    public infix fun String.put(value: Value?) {
         set(this, value)
     }
 
-    infix fun String.put(string: String?) {
+    public infix fun String.put(string: String?) {
         set(this, string?.asValue())
     }
 
-    infix fun String.put(number: Number?) {
+    public infix fun String.put(number: Number?) {
         set(this, number?.asValue())
     }
 
-    infix fun String.put(boolean: Boolean?) {
+    public infix fun String.put(boolean: Boolean?) {
         set(this, boolean?.asValue())
     }
 
-    infix fun String.put(enum: Enum<*>) {
+    public infix fun String.put(enum: Enum<*>) {
         set(this, EnumValue(enum))
     }
 
     @JvmName("putValues")
-    infix fun String.put(iterable: Iterable<Value>) {
+    public infix fun String.put(iterable: Iterable<Value>) {
         set(this, iterable.asValue())
     }
 
     @JvmName("putNumbers")
-    infix fun String.put(iterable: Iterable<Number>) {
+    public infix fun String.put(iterable: Iterable<Number>) {
         set(this, iterable.map { it.asValue() }.asValue())
     }
 
     @JvmName("putStrings")
-    infix fun String.put(iterable: Iterable<String>) {
+    public infix fun String.put(iterable: Iterable<String>) {
         set(this, iterable.map { it.asValue() }.asValue())
     }
 
-    infix fun String.put(array: DoubleArray) {
+    public infix fun String.put(array: DoubleArray) {
         set(this, array.asValue())
     }
 
-    infix fun String.putValue(any: Any?) {
-        set(this, Value.of(any))
-    }
-
-    infix fun String.put(meta: Meta?) {
+    public infix fun String.put(meta: Meta?) {
         this@MetaBuilder[this] = meta
     }
 
-    infix fun String.put(repr: MetaRepr?) {
+    public infix fun String.put(repr: MetaRepr?) {
         set(this, repr?.toMeta())
     }
 
     @JvmName("putMetas")
-    infix fun String.put(value: Iterable<Meta>) {
-        this@MetaBuilder[this] = value.toList()
+    public infix fun String.put(value: Iterable<Meta>) {
+        set(this,value.toList())
     }
 
-    infix fun String.put(metaBuilder: MetaBuilder.() -> Unit) {
+    public infix fun String.put(metaBuilder: MetaBuilder.() -> Unit) {
         this@MetaBuilder[this] = MetaBuilder().apply(metaBuilder)
     }
 
-    infix fun Name.put(value: Value?) {
+    public infix fun Name.put(value: Value?) {
         set(this, value)
     }
 
-    infix fun Name.put(string: String?) {
+    public infix fun Name.put(string: String?) {
         set(this, string?.asValue())
     }
 
-    infix fun Name.put(number: Number?) {
+    public infix fun Name.put(number: Number?) {
         set(this, number?.asValue())
     }
 
-    infix fun Name.put(boolean: Boolean?) {
+    public infix fun Name.put(boolean: Boolean?) {
         set(this, boolean?.asValue())
     }
 
-    infix fun Name.put(enum: Enum<*>) {
+    public infix fun Name.put(enum: Enum<*>) {
         set(this, EnumValue(enum))
     }
 
     @JvmName("putValues")
-    infix fun Name.put(iterable: Iterable<Value>) {
+    public infix fun Name.put(iterable: Iterable<Value>) {
         set(this, iterable.asValue())
     }
 
-    infix fun Name.put(meta: Meta?) {
+    public infix fun Name.put(meta: Meta?) {
         this@MetaBuilder[this] = meta
     }
 
-    infix fun Name.put(repr: MetaRepr?) {
+    public infix fun Name.put(repr: MetaRepr?) {
         set(this, repr?.toMeta())
     }
 
     @JvmName("putMetas")
-    infix fun Name.put(value: Iterable<Meta>) {
-        this@MetaBuilder[this] = value.toList()
+    public infix fun Name.put(value: Iterable<Meta>) {
+        set(this, value.toList())
     }
 
-    infix fun Name.put(metaBuilder: MetaBuilder.() -> Unit) {
+    public infix fun Name.put(metaBuilder: MetaBuilder.() -> Unit) {
         this@MetaBuilder[this] = MetaBuilder().apply(metaBuilder)
     }
 }
@@ -125,7 +121,7 @@ class MetaBuilder : AbstractMutableMeta<MetaBuilder>() {
 /**
  * For safety, builder always copies the initial meta even if it is builder itself
  */
-fun Meta.builder(): MetaBuilder {
+public fun Meta.builder(): MetaBuilder {
     return MetaBuilder().also { builder ->
         items.mapValues { entry ->
             val item = entry.value
@@ -140,16 +136,10 @@ fun Meta.builder(): MetaBuilder {
 /**
  * Create a deep copy of this meta and apply builder to it
  */
-fun Meta.edit(builder: MetaBuilder.() -> Unit): MetaBuilder = builder().apply(builder)
-
-/**
- * Build a [MetaBuilder] using given transformation
- */
-@Deprecated("To be replaced with fake constructor", ReplaceWith("Meta"))
-fun buildMeta(builder: MetaBuilder.() -> Unit): MetaBuilder = MetaBuilder().apply(builder)
+public fun Meta.edit(builder: MetaBuilder.() -> Unit): MetaBuilder = builder().apply(builder)
 
 /**
  * Build a [MetaBuilder] using given transformation
  */
 @Suppress("FunctionName")
-fun Meta(builder: MetaBuilder.() -> Unit): MetaBuilder = MetaBuilder().apply(builder)
\ No newline at end of file
+public fun Meta(builder: MetaBuilder.() -> Unit): MetaBuilder = MetaBuilder().apply(builder)
\ No newline at end of file
diff --git a/dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/MetaSerializer.kt b/dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/MetaSerializer.kt
index 6f0db59e..b20adba8 100644
--- a/dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/MetaSerializer.kt
+++ b/dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/MetaSerializer.kt
@@ -1,28 +1,68 @@
 package hep.dataforge.meta
 
 import hep.dataforge.names.NameToken
-import kotlinx.serialization.*
+import hep.dataforge.values.ValueSerializer
+import kotlinx.serialization.ExperimentalSerializationApi
+import kotlinx.serialization.InternalSerializationApi
+import kotlinx.serialization.KSerializer
 import kotlinx.serialization.builtins.MapSerializer
-import kotlinx.serialization.json.JsonInput
-import kotlinx.serialization.json.JsonObjectSerializer
-import kotlinx.serialization.json.JsonOutput
+import kotlinx.serialization.descriptors.*
+import kotlinx.serialization.encoding.*
+import kotlinx.serialization.json.JsonDecoder
+import kotlinx.serialization.json.JsonEncoder
+import kotlinx.serialization.json.JsonObject
 
+@OptIn(ExperimentalSerializationApi::class)
+public object MetaItemSerializer : KSerializer<MetaItem<*>> {
+
+    @OptIn(InternalSerializationApi::class)
+    override val descriptor: SerialDescriptor = buildClassSerialDescriptor("hep.dataforge.meta.MetaItem") {
+        element<Boolean>("isNode")
+        element("content", buildSerialDescriptor("MetaItem.content", PolymorphicKind.SEALED))
+    }
+
+    override fun deserialize(decoder: Decoder): MetaItem<*> {
+        decoder.decodeStructure(descriptor) {
+            //Force strict serialization order
+            require(decodeElementIndex(descriptor) == 0) { "Node flag must be first item serialized" }
+            val isNode = decodeBooleanElement(descriptor, 0)
+            require(decodeElementIndex(descriptor) == 1) { "Missing MetaItem content" }
+            val item = if (isNode) {
+                decodeSerializableElement(descriptor,1, MetaSerializer).asMetaItem()
+            } else {
+                decodeSerializableElement(descriptor,1,ValueSerializer).asMetaItem()
+            }
+            require(decodeElementIndex(descriptor) == CompositeDecoder.DECODE_DONE){"Serialized MetaItem contains additional fields"}
+            return  item
+        }
+    }
+
+    override fun serialize(encoder: Encoder, value: MetaItem<*>) {
+        encoder.encodeStructure(descriptor) {
+            encodeBooleanElement(descriptor, 0, value is MetaItem.NodeItem)
+            when (value) {
+                is MetaItem.ValueItem -> encodeSerializableElement(descriptor, 1, ValueSerializer, value.value)
+                is MetaItem.NodeItem -> encodeSerializableElement(descriptor, 1, MetaSerializer, value.node)
+            }
+        }
+    }
+}
 
 /**
  * Serialized for meta
  */
-@Serializer(Meta::class)
-object MetaSerializer : KSerializer<Meta> {
-    private val mapSerializer = MapSerializer(
-        NameToken.serializer(),
-        MetaItem.serializer(MetaSerializer)
+public object MetaSerializer : KSerializer<Meta> {
+
+    private val mapSerializer: KSerializer<Map<NameToken, MetaItem<Meta>>> = MapSerializer(
+        NameToken,
+        MetaItemSerializer//MetaItem.serializer(MetaSerializer)
     )
 
     override val descriptor: SerialDescriptor get() = mapSerializer.descriptor
 
     override fun deserialize(decoder: Decoder): Meta {
-        return if (decoder is JsonInput) {
-            JsonObjectSerializer.deserialize(decoder).toMeta()
+        return if (decoder is JsonDecoder) {
+            JsonObject.serializer().deserialize(decoder).toMeta()
         } else {
             object : MetaBase() {
                 override val items: Map<NameToken, MetaItem<*>> = mapSerializer.deserialize(decoder)
@@ -31,8 +71,8 @@ object MetaSerializer : KSerializer<Meta> {
     }
 
     override fun serialize(encoder: Encoder, value: Meta) {
-        if (encoder is JsonOutput) {
-            JsonObjectSerializer.serialize(encoder, value.toJson())
+        if (encoder is JsonEncoder) {
+            JsonObject.serializer().serialize(encoder, value.toJson())
         } else {
             mapSerializer.serialize(encoder, value.items)
         }
diff --git a/dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/MetaWithDefault.kt b/dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/MetaWithDefault.kt
new file mode 100644
index 00000000..2a225121
--- /dev/null
+++ b/dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/MetaWithDefault.kt
@@ -0,0 +1,18 @@
+package hep.dataforge.meta
+
+import hep.dataforge.names.Name
+import hep.dataforge.names.NameToken
+
+/**
+ * Meta object with default provider for items not present in the initial meta.
+ */
+public class MetaWithDefault(public val meta: Meta, public val default: ItemProvider) : MetaBase() {
+    override val items: Map<NameToken, MetaItem<*>>
+        get() = meta.items
+
+    override fun getItem(name: Name): MetaItem<*>? {
+        return meta[name] ?: default.getItem(name)
+    }
+}
+
+public fun Meta.withDefault(default: ItemProvider): MetaWithDefault = MetaWithDefault(this, default)
\ No newline at end of file
diff --git a/dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/MutableItemDelegate.kt b/dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/MutableItemDelegate.kt
index 3885b809..32a7c7d4 100644
--- a/dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/MutableItemDelegate.kt
+++ b/dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/MutableItemDelegate.kt
@@ -5,163 +5,189 @@ import hep.dataforge.names.Name
 import hep.dataforge.names.asName
 import hep.dataforge.values.DoubleArrayValue
 import hep.dataforge.values.Value
-import hep.dataforge.values.stringList
+import hep.dataforge.values.asValue
+import hep.dataforge.values.doubleArray
 import kotlin.properties.ReadWriteProperty
 import kotlin.reflect.KProperty
 
 /* Read-write delegates */
 
-open class MutableItemDelegate(
-    override val owner: MutableItemProvider,
-    key: Name? = null,
-    default: MetaItem<*>? = null
-) : ItemDelegate(owner, key, default), ReadWriteProperty<Any?, MetaItem<*>?> {
+public typealias MutableItemDelegate = ReadWriteProperty<Any?, MetaItem<*>?>
+
+public fun MutableItemProvider.item(key: Name? = null): MutableItemDelegate = object : MutableItemDelegate {
+    override fun getValue(thisRef: Any?, property: KProperty<*>): MetaItem<*>? {
+        return getItem(key ?: property.name.asName())
+    }
 
     override fun setValue(thisRef: Any?, property: KProperty<*>, value: MetaItem<*>?) {
         val name = key ?: property.name.asName()
-        owner.setItem(name, value)
+        setItem(name, value)
     }
 }
 
-fun MutableItemProvider.item(key: Name? = null): MutableItemDelegate =
-    MutableItemDelegate(this, key)
+/* Mutable converters */
 
-//Read-write delegates
+/**
+ * A type converter for a mutable [MetaItem] delegate
+ */
+public fun <R : Any> MutableItemDelegate.convert(
+    converter: MetaConverter<R>,
+): ReadWriteProperty<Any?, R?> = object : ReadWriteProperty<Any?, R?> {
+
+    override fun getValue(thisRef: Any?, property: KProperty<*>): R? =
+        this@convert.getValue(thisRef, property)?.let(converter::itemToObject)
+
+    override fun setValue(thisRef: Any?, property: KProperty<*>, value: R?) {
+        val item = value?.let(converter::objectToMetaItem)
+        this@convert.setValue(thisRef, property, item)
+    }
+}
+
+public fun <R : Any> MutableItemDelegate.convert(
+    converter: MetaConverter<R>,
+    default: () -> R,
+): ReadWriteProperty<Any?, R> = object : ReadWriteProperty<Any?, R> {
+
+    override fun getValue(thisRef: Any?, property: KProperty<*>): R =
+        this@convert.getValue(thisRef, property)?.let(converter::itemToObject) ?: default()
+
+    override fun setValue(thisRef: Any?, property: KProperty<*>, value: R) {
+        val item = value.let(converter::objectToMetaItem)
+        this@convert.setValue(thisRef, property, item)
+    }
+}
+
+public fun <R> MutableItemDelegate.convert(
+    reader: (MetaItem<*>?) -> R,
+    writer: (R) -> MetaItem<*>?,
+): ReadWriteProperty<Any?, R> = object : ReadWriteProperty<Any?, R> {
+
+    override fun getValue(thisRef: Any?, property: KProperty<*>): R =
+        this@convert.getValue(thisRef, property).let(reader)
+
+    override fun setValue(thisRef: Any?, property: KProperty<*>, value: R) {
+        val item = value?.let(writer)
+        this@convert.setValue(thisRef, property, item)
+    }
+}
+
+
+
+/* Read-write delegates for [MutableItemProvider] */
 
 /**
  * A property delegate that uses custom key
  */
-fun MutableItemProvider.value(key: Name? = null): ReadWriteProperty<Any?, Value?> =
+public fun MutableItemProvider.value(key: Name? = null): ReadWriteProperty<Any?, Value?> =
     item(key).convert(MetaConverter.value)
 
-fun MutableItemProvider.string(key: Name? = null): ReadWriteProperty<Any?, String?> =
+public fun MutableItemProvider.string(key: Name? = null): ReadWriteProperty<Any?, String?> =
     item(key).convert(MetaConverter.string)
 
-fun MutableItemProvider.boolean(key: Name? = null): ReadWriteProperty<Any?, Boolean?> =
+public fun MutableItemProvider.boolean(key: Name? = null): ReadWriteProperty<Any?, Boolean?> =
     item(key).convert(MetaConverter.boolean)
 
-fun MutableItemProvider.number(key: Name? = null): ReadWriteProperty<Any?, Number?> =
+public fun MutableItemProvider.number(key: Name? = null): ReadWriteProperty<Any?, Number?> =
     item(key).convert(MetaConverter.number)
 
-fun MutableItemProvider.string(default: String, key: Name? = null): ReadWriteProperty<Any?, String> =
+public fun MutableItemProvider.string(default: String, key: Name? = null): ReadWriteProperty<Any?, String> =
     item(key).convert(MetaConverter.string) { default }
 
-fun MutableItemProvider.boolean(default: Boolean, key: Name? = null): ReadWriteProperty<Any?, Boolean> =
+public fun MutableItemProvider.boolean(default: Boolean, key: Name? = null): ReadWriteProperty<Any?, Boolean> =
     item(key).convert(MetaConverter.boolean) { default }
 
-fun MutableItemProvider.number(default: Number, key: Name? = null): ReadWriteProperty<Any?, Number> =
+public fun MutableItemProvider.number(default: Number, key: Name? = null): ReadWriteProperty<Any?, Number> =
     item(key).convert(MetaConverter.number) { default }
 
-fun MutableItemProvider.value(key: Name? = null, default: () -> Value): ReadWriteProperty<Any?, Value> =
+public fun MutableItemProvider.value(key: Name? = null, default: () -> Value): ReadWriteProperty<Any?, Value> =
     item(key).convert(MetaConverter.value, default)
 
-fun MutableItemProvider.string(key: Name? = null, default: () -> String): ReadWriteProperty<Any?, String> =
+public fun MutableItemProvider.string(key: Name? = null, default: () -> String): ReadWriteProperty<Any?, String> =
     item(key).convert(MetaConverter.string, default)
 
-fun MutableItemProvider.boolean(key: Name? = null, default: () -> Boolean): ReadWriteProperty<Any?, Boolean> =
+public fun MutableItemProvider.boolean(key: Name? = null, default: () -> Boolean): ReadWriteProperty<Any?, Boolean> =
     item(key).convert(MetaConverter.boolean, default)
 
-fun MutableItemProvider.number(key: Name? = null, default: () -> Number): ReadWriteProperty<Any?, Number> =
+public fun MutableItemProvider.number(key: Name? = null, default: () -> Number): ReadWriteProperty<Any?, Number> =
     item(key).convert(MetaConverter.number, default)
 
-inline fun <reified E : Enum<E>> MutableItemProvider.enum(default: E, key: Name? = null): ReadWriteProperty<Any?, E> =
+public inline fun <reified E : Enum<E>> MutableItemProvider.enum(
+    default: E,
+    key: Name? = null,
+): ReadWriteProperty<Any?, E> =
     item(key).convert(MetaConverter.enum()) { default }
 
-inline fun <reified M : MutableMeta<M>> M.node(key: Name? = null): ReadWriteProperty<Any?, M?> =
+public inline fun <reified M : MutableMeta<M>> M.node(key: Name? = null): ReadWriteProperty<Any?, M?> =
     item(key).convert(reader = { it?.let { it.node as M } }, writer = { it?.let { MetaItem.NodeItem(it) } })
 
+/* Number delegates */
 
-fun <T> MutableItemProvider.item(
-    default: T? = null,
-    key: Name? = null,
-    writer: (T) -> MetaItem<*>? = { MetaItem.of(it) },
-    reader: (MetaItem<*>?) -> T
-): ReadWriteProperty<Any?, T> = MutableItemDelegate(
-    this,
-    key,
-    default?.let { MetaItem.of(it) }
-).convert(reader = reader, writer = writer)
-
-fun Configurable.value(key: Name? = null): ReadWriteProperty<Any?, Value?> =
-    item(key).convert(MetaConverter.value)
-
-fun <T> MutableItemProvider.value(
-    default: T? = null,
-    key: Name? = null,
-    writer: (T) -> Value? = { Value.of(it) },
-    reader: (Value?) -> T
-): ReadWriteProperty<Any?, T> = MutableItemDelegate(
-    this,
-    key,
-    default?.let { MetaItem.of(it) }
-).convert(
-    reader = { reader(it.value) },
-    writer = { value -> writer(value)?.let { MetaItem.ValueItem(it) } }
-)
-
-/* Number delegates*/
-
-fun MutableItemProvider.int(key: Name? = null): ReadWriteProperty<Any?, Int?> =
+public fun MutableItemProvider.int(key: Name? = null): ReadWriteProperty<Any?, Int?> =
     item(key).convert(MetaConverter.int)
 
-fun MutableItemProvider.double(key: Name? = null): ReadWriteProperty<Any?, Double?> =
+public fun MutableItemProvider.double(key: Name? = null): ReadWriteProperty<Any?, Double?> =
     item(key).convert(MetaConverter.double)
 
-fun MutableItemProvider.long(key: Name? = null): ReadWriteProperty<Any?, Long?> =
+public fun MutableItemProvider.long(key: Name? = null): ReadWriteProperty<Any?, Long?> =
     item(key).convert(MetaConverter.long)
 
-fun MutableItemProvider.float(key: Name? = null): ReadWriteProperty<Any?, Float?> =
+public fun MutableItemProvider.float(key: Name? = null): ReadWriteProperty<Any?, Float?> =
     item(key).convert(MetaConverter.float)
 
 
 /* Safe number delegates*/
 
-fun MutableItemProvider.int(default: Int, key: Name? = null): ReadWriteProperty<Any?, Int> =
+public fun MutableItemProvider.int(default: Int, key: Name? = null): ReadWriteProperty<Any?, Int> =
     item(key).convert(MetaConverter.int) { default }
 
-fun MutableItemProvider.double(default: Double, key: Name? = null): ReadWriteProperty<Any?, Double> =
+public fun MutableItemProvider.double(default: Double, key: Name? = null): ReadWriteProperty<Any?, Double> =
     item(key).convert(MetaConverter.double) { default }
 
-fun MutableItemProvider.long(default: Long, key: Name? = null): ReadWriteProperty<Any?, Long> =
+public fun MutableItemProvider.long(default: Long, key: Name? = null): ReadWriteProperty<Any?, Long> =
     item(key).convert(MetaConverter.long) { default }
 
-fun MutableItemProvider.float(default: Float, key: Name? = null): ReadWriteProperty<Any?, Float> =
+public fun MutableItemProvider.float(default: Float, key: Name? = null): ReadWriteProperty<Any?, Float> =
     item(key).convert(MetaConverter.float) { default }
 
 
-/*
- * Extra delegates for special cases
- */
-fun MutableItemProvider.stringList(vararg strings: String, key: Name? = null): ReadWriteProperty<Any?, List<String>> =
-    item(listOf(*strings), key) {
-        it?.value?.stringList ?: emptyList()
-    }
+/* Extra delegates for special cases */
 
-fun MutableItemProvider.stringListOrNull(
-    vararg strings: String,
-    key: Name? = null
-): ReadWriteProperty<Any?, List<String>?> =
-    item(listOf(*strings), key) {
-        it?.value?.stringList
-    }
+public fun MutableItemProvider.stringList(
+    vararg default: String,
+    key: Name? = null,
+): ReadWriteProperty<Any?, List<String>> = item(key).convert(
+    reader = { it?.stringList ?: listOf(*default) },
+    writer = { it.map { str -> str.asValue() }.asValue().asMetaItem() }
+)
 
-fun MutableItemProvider.numberList(vararg numbers: Number, key: Name? = null): ReadWriteProperty<Any?, List<Number>> =
-    item(listOf(*numbers), key) { item ->
-        item?.value?.list?.map { it.number } ?: emptyList()
-    }
+public fun MutableItemProvider.stringList(
+    key: Name? = null,
+): ReadWriteProperty<Any?, List<String>?> = item(key).convert(
+    reader = { it?.stringList },
+    writer = { it?.map { str -> str.asValue() }?.asValue()?.asMetaItem() }
+)
 
-/**
- * A special delegate for double arrays
- */
-fun MutableItemProvider.doubleArray(vararg doubles: Double, key: Name? = null): ReadWriteProperty<Any?, DoubleArray> =
-    item(doubleArrayOf(*doubles), key) {
-        (it.value as? DoubleArrayValue)?.value
-            ?: it?.value?.list?.map { value -> value.number.toDouble() }?.toDoubleArray()
-            ?: doubleArrayOf()
-    }
+public fun MutableItemProvider.numberList(
+    vararg default: Number,
+    key: Name? = null,
+): ReadWriteProperty<Any?, List<Number>> = item(key).convert(
+    reader = { it?.value?.list?.map { value -> value.number } ?: listOf(*default) },
+    writer = { it.map { num -> num.asValue() }.asValue().asMetaItem() }
+)
 
-fun <T> MutableItemProvider.listValue(
+/* A special delegate for double arrays */
+
+
+public fun MutableItemProvider.doubleArray(
+    vararg default: Double,
+    key: Name? = null,
+): ReadWriteProperty<Any?, DoubleArray> = item(key).convert(
+    reader = { it?.value?.doubleArray ?: doubleArrayOf(*default) },
+    writer = { DoubleArrayValue(it).asMetaItem() }
+)
+
+public fun <T> MutableItemProvider.listValue(
     key: Name? = null,
     writer: (T) -> Value = { Value.of(it) },
-    reader: (Value) -> T
+    reader: (Value) -> T,
 ): ReadWriteProperty<Any?, List<T>?> = item(key).convert(MetaConverter.valueList(writer, reader))
diff --git a/dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/MutableItemProvider.kt b/dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/MutableItemProvider.kt
new file mode 100644
index 00000000..6a43af6e
--- /dev/null
+++ b/dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/MutableItemProvider.kt
@@ -0,0 +1,88 @@
+package hep.dataforge.meta
+
+import hep.dataforge.names.*
+import hep.dataforge.values.Value
+import kotlin.properties.ReadWriteProperty
+
+public interface MutableItemProvider : ItemProvider {
+    public fun setItem(name: Name, item: MetaItem<*>?)
+}
+
+public fun MutableItemProvider.getItem(key: String): MetaItem<*>? = getItem(key.toName())
+
+public fun MutableItemProvider.setValue(name: Name, value: Value?): Unit =
+    setItem(name, value?.let { MetaItem.ValueItem(value) })
+
+public fun MutableItemProvider.setNode(name: Name, meta: Meta?): Unit =
+    setItem(name, meta?.let { MetaItem.NodeItem(meta) })
+
+public fun MutableItemProvider.setItem(key: String, item: MetaItem<*>?): Unit = setItem(key.toName(), item)
+
+public fun MutableItemProvider.setValue(key: String, value: Value?): Unit =
+    setItem(key, value?.let { MetaItem.ValueItem(value) })
+
+public fun MutableItemProvider.setNode(key: String, meta: Meta?): Unit =
+    setItem(key, meta?.let { MetaItem.NodeItem(meta) })
+
+public fun MutableItemProvider.node(key: Name? = null): ReadWriteProperty<Any?, Meta?> = item(key).convert(
+    reader = { it.node },
+    writer = { it?.let { MetaItem.NodeItem(it) } }
+)
+
+@Suppress("NOTHING_TO_INLINE")
+public inline fun MutableItemProvider.remove(name: Name): Unit = setItem(name, null)
+
+@Suppress("NOTHING_TO_INLINE")
+public inline fun MutableItemProvider.remove(name: String): Unit = remove(name.toName())
+
+
+/**
+ * Universal unsafe set method
+ */
+public operator fun MutableItemProvider.set(name: Name, value: Any?) {
+    when (value) {
+        null -> remove(name)
+        is MetaItem<*> -> setItem(name, value)
+        is Meta -> setNode(name, value)
+        is Configurable -> setNode(name, value.config)
+        else -> setValue(name, Value.of(value))
+    }
+}
+
+public operator fun MutableItemProvider.set(name: NameToken, value: Any?): Unit =
+    set(name.asName(), value)
+
+public operator fun MutableItemProvider.set(key: String, value: Any?): Unit =
+    set(key.toName(), value)
+
+public operator fun MutableItemProvider.set(key: String, index: String, value: Any?): Unit =
+    set(key.toName().withIndex(index), value)
+
+
+
+/* Same name siblings generation */
+
+public fun MutableItemProvider.setIndexedItems(
+    name: Name,
+    items: Iterable<MetaItem<*>>,
+    indexFactory: (MetaItem<*>, index: Int) -> String = { _, index -> index.toString() }
+) {
+    val tokens = name.tokens.toMutableList()
+    val last = tokens.last()
+    items.forEachIndexed { index, meta ->
+        val indexedToken = NameToken(last.body, last.index + indexFactory(meta, index))
+        tokens[tokens.lastIndex] = indexedToken
+        setItem(Name(tokens), meta)
+    }
+}
+
+public fun MutableItemProvider.setIndexed(
+    name: Name,
+    metas: Iterable<Meta>,
+    indexFactory: (Meta, index: Int) -> String = { _, index -> index.toString() }
+) {
+    setIndexedItems(name, metas.map { MetaItem.NodeItem(it) }) { item, index -> indexFactory(item.node!!, index) }
+}
+
+public operator fun MutableItemProvider.set(name: Name, metas: Iterable<Meta>): Unit = setIndexed(name, metas)
+public operator fun MutableItemProvider.set(name: String, metas: Iterable<Meta>): Unit = setIndexed(name.toName(), metas)
diff --git a/dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/MutableMeta.kt b/dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/MutableMeta.kt
index 03245b00..7903ba87 100644
--- a/dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/MutableMeta.kt
+++ b/dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/MutableMeta.kt
@@ -1,13 +1,8 @@
 package hep.dataforge.meta
 
 import hep.dataforge.names.*
-import hep.dataforge.values.Value
 
-interface MutableItemProvider : ItemProvider {
-    fun setItem(name: Name, item: MetaItem<*>?)
-}
-
-interface MutableMeta<out M : MutableMeta<M>> : MetaNode<M>, MutableItemProvider {
+public interface MutableMeta<out M : MutableMeta<M>> : MetaNode<M>, MutableItemProvider {
     override val items: Map<NameToken, MetaItem<M>>
 //    fun onChange(owner: Any? = null, action: (Name, MetaItem<*>?, MetaItem<*>?) -> Unit)
 //    fun removeListener(owner: Any? = null)
@@ -18,19 +13,19 @@ interface MutableMeta<out M : MutableMeta<M>> : MetaNode<M>, MutableItemProvider
  *
  * Changes in Meta are not thread safe.
  */
-abstract class AbstractMutableMeta<M : MutableMeta<M>> : AbstractMetaNode<M>(), MutableMeta<M> {
-    protected val _items: MutableMap<NameToken, MetaItem<M>> = LinkedHashMap()
+public abstract class AbstractMutableMeta<M : MutableMeta<M>> : AbstractMetaNode<M>(), MutableMeta<M> {
+    protected val children: MutableMap<NameToken, MetaItem<M>> = LinkedHashMap()
 
     override val items: Map<NameToken, MetaItem<M>>
-        get() = _items
+        get() = children
 
     //protected abstract fun itemChanged(name: Name, oldItem: MetaItem<*>?, newItem: MetaItem<*>?)
 
     protected open fun replaceItem(key: NameToken, oldItem: MetaItem<M>?, newItem: MetaItem<M>?) {
         if (newItem == null) {
-            _items.remove(key)
+            children.remove(key)
         } else {
-            _items[key] = newItem
+            children[key] = newItem
         }
         //itemChanged(key.asName(), oldItem, newItem)
     }
@@ -56,12 +51,12 @@ abstract class AbstractMutableMeta<M : MutableMeta<M>> : AbstractMetaNode<M>(),
         when (name.length) {
             0 -> error("Can't setValue meta item for empty name")
             1 -> {
-                val token = name.first()!!
+                val token = name.firstOrNull()!!
                 @Suppress("UNCHECKED_CAST") val oldItem: MetaItem<M>? = get(name) as? MetaItem<M>
                 replaceItem(token, oldItem, wrapItem(item))
             }
             else -> {
-                val token = name.first()!!
+                val token = name.firstOrNull()!!
                 //get existing or create new node. Query is ignored for new node
                 if (items[token] == null) {
                     replaceItem(token, null, MetaItem.NodeItem(empty()))
@@ -72,52 +67,13 @@ abstract class AbstractMutableMeta<M : MutableMeta<M>> : AbstractMetaNode<M>(),
     }
 }
 
-
-@Suppress("NOTHING_TO_INLINE")
-inline fun MutableMeta<*>.remove(name: Name) = setItem(name, null)
-
-@Suppress("NOTHING_TO_INLINE")
-inline fun MutableMeta<*>.remove(name: String) = remove(name.toName())
-
-operator fun MutableMeta<*>.set(name: Name, item: MetaItem<*>?) = setItem(name, item)
-
-fun MutableMeta<*>.setValue(name: Name, value: Value) = setItem(name, MetaItem.ValueItem(value))
-
-fun MutableMeta<*>.setValue(name: String, value: Value) = set(name.toName(), value)
-
-fun MutableMeta<*>.setItem(name: String, item: MetaItem<*>?) = setItem(name.toName(), item)
-
-fun MutableMeta<*>.setNode(name: Name, node: Meta) =
-    setItem(name, MetaItem.NodeItem(node))
-
-fun MutableMeta<*>.setNode(name: String, node: Meta) = setNode(name.toName(), node)
-
-/**
- * Universal unsafe set method
- */
-operator fun MutableMeta<*>.set(name: Name, value: Any?) {
-    when (value) {
-        null -> remove(name)
-        is MetaItem<*> -> setItem(name, value)
-        is Meta -> setNode(name, value)
-        is Configurable -> setNode(name, value.config)
-        else -> setValue(name, Value.of(value))
-    }
-}
-
-operator fun MutableMeta<*>.set(name: NameToken, value: Any?) = set(name.asName(), value)
-
-operator fun MutableMeta<*>.set(key: String, value: Any?) = set(key.toName(), value)
-
-operator fun MutableMeta<*>.set(key: String, index: String, value: Any?) = set(key.toName().withIndex(index), value)
-
 /**
  * Update existing mutable node with another node. The rules are following:
  *  * value replaces anything
  *  * node updates node and replaces anything but node
  *  * node list updates node list if number of nodes in the list is the same and replaces anything otherwise
  */
-fun <M : MutableMeta<M>> M.update(meta: Meta) {
+public fun <M : MutableMeta<M>> M.update(meta: Meta) {
     meta.items.forEach { entry ->
         when (val value = entry.value) {
             is MetaItem.ValueItem -> setValue(entry.key.asName(), value.value)
@@ -127,54 +83,27 @@ fun <M : MutableMeta<M>> M.update(meta: Meta) {
     }
 }
 
-/* Same name siblings generation */
-
-fun MutableMeta<*>.setIndexedItems(
-    name: Name,
-    items: Iterable<MetaItem<*>>,
-    indexFactory: (MetaItem<*>, index: Int) -> String = { _, index -> index.toString() }
-) {
-    val tokens = name.tokens.toMutableList()
-    val last = tokens.last()
-    items.forEachIndexed { index, meta ->
-        val indexedToken = NameToken(last.body, last.index + indexFactory(meta, index))
-        tokens[tokens.lastIndex] = indexedToken
-        setItem(Name(tokens), meta)
-    }
-}
-
-fun MutableMeta<*>.setIndexed(
-    name: Name,
-    metas: Iterable<Meta>,
-    indexFactory: (Meta, index: Int) -> String = { _, index -> index.toString() }
-) {
-    setIndexedItems(name, metas.map { MetaItem.NodeItem(it) }) { item, index -> indexFactory(item.node!!, index) }
-}
-
-operator fun MutableMeta<*>.set(name: Name, metas: Iterable<Meta>): Unit = setIndexed(name, metas)
-operator fun MutableMeta<*>.set(name: String, metas: Iterable<Meta>): Unit = setIndexed(name.toName(), metas)
-
 /**
  * Append the node with a same-name-sibling, automatically generating numerical index
  */
-fun <M : MutableMeta<M>> M.append(name: Name, value: Any?) {
+public fun <M : MutableMeta<M>> M.append(name: Name, value: Any?) {
     require(!name.isEmpty()) { "Name could not be empty for append operation" }
-    val newIndex = name.last()!!.index
-    if (newIndex.isNotEmpty()) {
+    val newIndex = name.lastOrNull()!!.index
+    if (newIndex != null) {
         set(name, value)
     } else {
-        val index = (getIndexed(name).keys.mapNotNull { it.toIntOrNull() }.max() ?: -1) + 1
+        val index = (getIndexed(name).keys.mapNotNull { it.toIntOrNull() }.maxOrNull() ?: -1) + 1
         set(name.withIndex(index.toString()), value)
     }
 }
 
-fun <M : MutableMeta<M>> M.append(name: String, value: Any?) = append(name.toName(), value)
+public fun <M : MutableMeta<M>> M.append(name: String, value: Any?): Unit = append(name.toName(), value)
 
 /**
  * Apply existing node with given [builder] or create a new element with it.
  */
 @DFExperimental
-fun <M : AbstractMutableMeta<M>> M.edit(name: Name, builder: M.() -> Unit) {
+public fun <M : AbstractMutableMeta<M>> M.edit(name: Name, builder: M.() -> Unit) {
     val item = when (val existingItem = get(name)) {
         null -> empty().also { set(name, it) }
         is MetaItem.NodeItem<M> -> existingItem.node
diff --git a/dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/Scheme.kt b/dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/Scheme.kt
index deec949f..1fc74316 100644
--- a/dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/Scheme.kt
+++ b/dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/Scheme.kt
@@ -3,28 +3,54 @@ package hep.dataforge.meta
 import hep.dataforge.meta.descriptors.*
 import hep.dataforge.names.Name
 import hep.dataforge.names.NameToken
-import hep.dataforge.names.plus
+import hep.dataforge.names.asName
 
 /**
  * A base for delegate-based or descriptor-based scheme. [Scheme] has an empty constructor to simplify usage from [Specification].
+ * Default item provider and [NodeDescriptor] are optional
  */
-open class Scheme() : Configurable, Described, MetaRepr {
-    constructor(config: Config, defaultProvider: (Name) -> MetaItem<*>?) : this() {
-        this.config = config
-        this.defaultProvider = defaultProvider
+public open class Scheme(
+    config: Config = Config(),
+    internal var default: ItemProvider? = null,
+    descriptor: NodeDescriptor? = null,
+) : Configurable, MutableItemProvider, Described, MetaRepr {
+
+    override var config: Config = config
+        internal set(value) {
+            //Fix problem with `init` blocks in specifications
+            field = value.apply { update(field) }
+        }
+
+    override var descriptor: NodeDescriptor? = descriptor
+        internal set
+
+
+    public fun getDefaultItem(name: Name): MetaItem<*>? {
+        return default?.getItem(name) ?: descriptor?.get(name)?.defaultItem()
     }
 
-    //constructor(config: Config, default: Meta) : this(config, { default[it] })
-    constructor(config: Config) : this(config, { null })
+    /**
+     * Get a property with default
+     */
+    override fun getItem(name: Name): MetaItem<*>? = config[name] ?: getDefaultItem(name)
 
-    final override var config: Config = Config()
-        internal set
+    /**
+     * Check if property with given [name] could be assigned to [item]
+     */
+    public fun validateItem(name: Name, item: MetaItem<*>?): Boolean {
+        val descriptor = descriptor?.get(name)
+        return descriptor?.validateItem(item) ?: true
+    }
 
-    var defaultProvider: (Name) -> MetaItem<*>? = { null }
-        internal set
-
-    override fun getDefaultItem(name: Name): MetaItem<*>? {
-        return defaultProvider(name) ?: descriptor?.get(name)?.defaultItem()
+    /**
+     * Set a configurable property
+     */
+    override fun setItem(name: Name, item: MetaItem<*>?) {
+        if (validateItem(name, item)) {
+            config.setItem(name, item)
+        } else {
+            error("Validation failed for property $name with value $item")
+        }
     }
 
     /**
@@ -32,56 +58,73 @@ open class Scheme() : Configurable, Described, MetaRepr {
      * values if default value is unavailable.
      * Values from [defaultProvider] completely replace
      */
-    open val defaultLayer: Meta get() = DefaultLayer(Name.EMPTY)
+    public open val defaultLayer: Meta
+        get() = object : MetaBase() {
+            override val items: Map<NameToken, MetaItem<*>> = buildMap {
+                descriptor?.items?.forEach { (key, itemDescriptor) ->
+                    val token = NameToken(key)
+                    val name = token.asName()
+                    val item = default?.getItem(name) ?: itemDescriptor.defaultItem()
+                    if (item != null) {
+                        put(token, item)
+                    }
+                }
+            }
+        }
 
     override fun toMeta(): Laminate = Laminate(config, defaultLayer)
 
-    private inner class DefaultLayer(val path: Name) : MetaBase() {
-        override val items: Map<NameToken, MetaItem<*>> =
-            (descriptor?.get(path) as? NodeDescriptor)?.items?.entries?.associate { (key, descriptor) ->
-                val token = NameToken(key)
-                val fullName = path + token
-                val item: MetaItem<*> = when (descriptor) {
-                    is ValueDescriptor -> getDefaultItem(fullName) ?: descriptor.defaultItem()
-                    is NodeDescriptor -> MetaItem.NodeItem(DefaultLayer(fullName))
-                }
-                token to item
-            } ?: emptyMap()
-    }
+    public fun isEmpty(): Boolean = config.isEmpty()
 }
 
-inline operator fun <T : Scheme> T.invoke(block: T.() -> Unit) = apply(block)
+/**
+ * A shortcut to edit a [Scheme] object in-place
+ */
+public inline operator fun <T : Scheme> T.invoke(block: T.() -> Unit): T = apply(block)
 
 /**
  * A specification for simplified generation of wrappers
  */
-open class SchemeSpec<T : Scheme>(val builder: () -> T) :
-    Specification<T> {
-    override fun empty(): T = builder()
+public open class SchemeSpec<T : Scheme>(
+    private val builder: (config: Config, defaultProvider: ItemProvider, descriptor: NodeDescriptor?) -> T,
+) : Specification<T>, Described {
 
-    override fun wrap(config: Config, defaultProvider: (Name) -> MetaItem<*>?): T {
-        return empty().apply {
+    public constructor(emptyBuilder: () -> T) : this({ config: Config, defaultProvider: ItemProvider, descriptor: NodeDescriptor? ->
+        emptyBuilder().apply {
             this.config = config
-            this.defaultProvider = defaultProvider
+            this.default = defaultProvider
+            this.descriptor = descriptor
         }
+    })
+
+    override fun read(meta: Meta, defaultProvider: ItemProvider): T =
+        builder(Config(), meta.withDefault(defaultProvider), descriptor)
+
+    override fun wrap(config: Config, defaultProvider: ItemProvider): T {
+        return builder(config, defaultProvider, descriptor)
     }
 
+    //TODO Generate descriptor from Scheme class
+    override val descriptor: NodeDescriptor? get() = null
+
     @Suppress("OVERRIDE_BY_INLINE")
-    final override inline operator fun invoke(action: T.() -> Unit) = empty().apply(action)
+    final override inline operator fun invoke(action: T.() -> Unit): T = empty().apply(action)
 }
 
-/**
- * A scheme that uses [Meta] as a default layer
- */
-open class MetaScheme(
-    val meta: Meta,
-    override val descriptor: NodeDescriptor? = null,
-    config: Config = Config()
-) : Scheme(config, meta::get) {
-    override val defaultLayer: Meta get() = Laminate(meta, descriptor?.defaultItem().node)
+///**
+// * A scheme that uses [Meta] as a default layer
+// */
+//public open class MetaScheme(
+//    private val meta: Meta,
+//    override val descriptor: NodeDescriptor? = null,
+//    config: Config = Config(),
+//) : Scheme(config, meta) {
+//    override val defaultLayer: Meta get() = Laminate(meta, descriptor?.defaultItem().node)
+//}
+
+public fun Meta.asScheme(): Scheme = Scheme().apply {
+    config = this@asScheme.asConfig()
 }
 
-fun Meta.asScheme() =
-    MetaScheme(this)
-
-fun <T : Configurable> Meta.toScheme(spec: Specification<T>, block: T.() -> Unit) = spec.wrap(this).apply(block)
\ No newline at end of file
+public fun <T : MutableItemProvider> Meta.toScheme(spec: Specification<T>, block: T.() -> Unit = {}): T =
+    spec.read(this).apply(block)
diff --git a/dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/Specification.kt b/dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/Specification.kt
index 85cf7b96..05c31dc3 100644
--- a/dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/Specification.kt
+++ b/dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/Specification.kt
@@ -1,67 +1,102 @@
 package hep.dataforge.meta
 
 import hep.dataforge.names.Name
+import hep.dataforge.names.asName
 import kotlin.jvm.JvmName
+import kotlin.properties.ReadWriteProperty
+import kotlin.reflect.KProperty
 
 /**
  * Allows to apply custom configuration in a type safe way to simple untyped configuration.
  * By convention [Scheme] companion should inherit this class
  *
  */
-interface Specification<T : Configurable> {
-    fun empty() = wrap()
+public interface Specification<T : MutableItemProvider> {
+    /**
+     * Read generic read-only meta with this [Specification] producing instance of desired type.
+     */
+    public fun read(meta: Meta, defaultProvider: ItemProvider = ItemProvider.EMPTY): T
 
     /**
-     * Wrap generic configuration producing instance of desired type
+     * Wrap mutable [Config], using it as inner storage (changes to [Specification] are reflected on [Config]
      */
-    fun wrap(config: Config = Config(), defaultProvider: (Name) -> MetaItem<*>? = { null }): T
+    public fun wrap(config: Config, defaultProvider: ItemProvider = ItemProvider.EMPTY): T =
+        read(config as Meta, defaultProvider)
 
-    operator fun invoke(action: T.() -> Unit): T = empty().apply(action)
+    /**
+     * Generate an empty object
+     */
+    public fun empty(): T = read(Meta.EMPTY)
+
+    /**
+     * A convenience method to use specifications in builders
+     */
+    public operator fun invoke(action: T.() -> Unit): T = empty().apply(action)
 }
 
 /**
  * Update given configuration using given type as a builder
  */
-fun <T : Configurable> Specification<T>.update(config: Config, action: T.() -> Unit): T = wrap(config).apply(action)
-
-/**
- * Wrap a configuration using static meta as default
- */
-fun <T : Configurable> Specification<T>.wrap(config: Config = Config(), default: Meta = Meta.EMPTY): T =
-    wrap(config) { default[it] }
-
-/**
- * Wrap a configuration using static meta as default
- */
-fun <T : Configurable> Specification<T>.wrap(source: Meta): T {
-    val default = source.seal()
-    return wrap(source.asConfig(), default)
-}
+public fun <T : MutableItemProvider> Specification<T>.update(meta: Meta, action: T.() -> Unit): T =
+    read(meta).apply(action)
 
 
 /**
  * Apply specified configuration to configurable
  */
-fun <T : Configurable, C : Configurable, S : Specification<C>> T.configure(spec: S, action: C.() -> Unit) =
-    apply { spec.update(config, action) }
+public fun <T : MetaRepr, C : MutableItemProvider, S : Specification<C>> T.configure(spec: S, action: C.() -> Unit): T =
+    apply { spec.update(toMeta(), action) }
 
 /**
  * Update configuration using given specification
  */
-fun <C : Configurable, S : Specification<C>> Configurable.update(spec: S, action: C.() -> Unit) =
+public fun <C : MutableItemProvider, S : Specification<C>> Configurable.update(
+    spec: S,
+    action: C.() -> Unit,
+): Configurable =
     apply { spec.update(config, action) }
 
 /**
  * Create a style based on given specification
  */
-fun <C : Configurable, S : Specification<C>> S.createStyle(action: C.() -> Unit): Meta =
+public fun <C : MutableItemProvider, S : Specification<C>> S.createStyle(action: C.() -> Unit): Meta =
     Config().also { update(it, action) }
 
-fun <T : Configurable> MetaItem<*>.spec(spec: Specification<T>): T? = node?.let {
+public fun <T : MutableItemProvider> MetaItem<*>.spec(spec: Specification<T>): T? = node?.let {
     spec.wrap(
         Config(), it
     )
 }
 
 @JvmName("configSpec")
-fun <T : Configurable> MetaItem<Config>.spec(spec: Specification<T>): T? = node?.let { spec.wrap(it) }
+public fun <T : MutableItemProvider> MetaItem<Config>.spec(spec: Specification<T>): T? = node?.let { spec.wrap(it) }
+
+public fun <T : Scheme> MutableItemProvider.spec(
+    spec: Specification<T>, key: Name? = null,
+): ReadWriteProperty<Any?, T?> = object : ReadWriteProperty<Any?, T?> {
+    override fun getValue(thisRef: Any?, property: KProperty<*>): T? {
+        val name = key ?: property.name.asName()
+        return getItem(name).node?.let { spec.read(it) }
+    }
+
+    override fun setValue(thisRef: Any?, property: KProperty<*>, value: T?) {
+        val name = key ?: property.name.asName()
+        setItem(name, value?.toMeta()?.asMetaItem())
+    }
+}
+
+public fun <T : Scheme> MutableItemProvider.spec(
+    spec: Specification<T>,
+    default: T,
+    key: Name? = null,
+): ReadWriteProperty<Any?, T> = object : ReadWriteProperty<Any?, T> {
+    override fun getValue(thisRef: Any?, property: KProperty<*>): T {
+        val name = key ?: property.name.asName()
+        return getItem(name).node?.let { spec.read(it) } ?: default
+    }
+
+    override fun setValue(thisRef: Any?, property: KProperty<*>, value: T) {
+        val name = key ?: property.name.asName()
+        setItem(name, value.toMeta().asMetaItem())
+    }
+}
\ No newline at end of file
diff --git a/dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/annotations.kt b/dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/annotations.kt
index 2085bc5d..69ffa8aa 100644
--- a/dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/annotations.kt
+++ b/dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/annotations.kt
@@ -4,8 +4,8 @@ package hep.dataforge.meta
  * General marker for dataforge builders
  */
 @DslMarker
-annotation class DFBuilder
+public annotation class DFBuilder
 
 @RequiresOptIn(level = RequiresOptIn.Level.WARNING)
 @Retention(AnnotationRetention.BINARY)
-annotation class DFExperimental
\ No newline at end of file
+public annotation class DFExperimental
\ No newline at end of file
diff --git a/dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/descriptors/Described.kt b/dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/descriptors/Described.kt
index ac8ba74a..4af17dfb 100644
--- a/dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/descriptors/Described.kt
+++ b/dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/descriptors/Described.kt
@@ -3,11 +3,11 @@ package hep.dataforge.meta.descriptors
 /**
  * An object which provides its descriptor
  */
-interface Described {
-    val descriptor: ItemDescriptor?
+public interface Described {
+    public val descriptor: ItemDescriptor?
 
-    companion object {
-        const val DESCRIPTOR_NODE = "@descriptor"
+    public companion object {
+        //public const val DESCRIPTOR_NODE: String = "@descriptor"
     }
 }
 
diff --git a/dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/descriptors/DescriptorMeta.kt b/dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/descriptors/DescriptorMeta.kt
index 47c90370..9a5b915d 100644
--- a/dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/descriptors/DescriptorMeta.kt
+++ b/dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/descriptors/DescriptorMeta.kt
@@ -1,32 +1,48 @@
 package hep.dataforge.meta.descriptors
 
 import hep.dataforge.meta.Laminate
+import hep.dataforge.meta.Meta
 import hep.dataforge.meta.MetaBase
 import hep.dataforge.meta.MetaItem
 import hep.dataforge.names.NameToken
-import hep.dataforge.values.Null
 
 /**
- * A [Meta] that wraps a descriptor node
+ * A [Meta] that is constructed from [NodeDescriptor]
  */
-class DescriptorMeta(val descriptor: NodeDescriptor) : MetaBase() {
+private class DescriptorMeta(val descriptor: NodeDescriptor) : Meta, MetaBase() {
     override val items: Map<NameToken, MetaItem<*>>
-        get() = descriptor.items.entries.associate { entry ->
-            NameToken(entry.key) to entry.value.defaultItem()
+        get() = buildMap {
+            descriptor.items.forEach { (token, descriptorItem) ->
+                val item = descriptorItem.defaultItem()
+                if (item != null) {
+                    put(NameToken(token), item)
+                }
+            }
         }
 }
 
-fun NodeDescriptor.buildDefaultMeta() = Laminate(default, DescriptorMeta(this))
+/**
+ * Generate a laminate representing default item set generated by this descriptor
+ */
+public fun NodeDescriptor.defaultMeta(): Laminate = Laminate(default, DescriptorMeta(this))
 
-fun NodeDescriptor.defaultItem(): MetaItem.NodeItem<*> =
-    MetaItem.NodeItem(buildDefaultMeta())
+/**
+ * Build a default [MetaItem.NodeItem] from this node descriptor
+ */
+internal fun NodeDescriptor.defaultItem(): MetaItem.NodeItem<*> =
+    MetaItem.NodeItem(defaultMeta())
 
-fun ValueDescriptor.defaultItem(): MetaItem.ValueItem = MetaItem.ValueItem(default ?: Null)
+/**
+ * Build a default [MetaItem.ValueItem] from this descriptor
+ */
+internal fun ValueDescriptor.defaultItem(): MetaItem.ValueItem? {
+    return MetaItem.ValueItem(default ?: return null)
+}
 
 /**
  * Build a default [MetaItem] from descriptor.
  */
-fun ItemDescriptor.defaultItem(): MetaItem<*> {
+public fun ItemDescriptor.defaultItem(): MetaItem<*>? {
     return when (this) {
         is ValueDescriptor -> defaultItem()
         is NodeDescriptor -> defaultItem()
diff --git a/dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/descriptors/ItemDescriptor.kt b/dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/descriptors/ItemDescriptor.kt
index a277e18d..cbb56fa1 100644
--- a/dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/descriptors/ItemDescriptor.kt
+++ b/dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/descriptors/ItemDescriptor.kt
@@ -4,29 +4,26 @@ import hep.dataforge.meta.*
 import hep.dataforge.names.*
 import hep.dataforge.values.*
 
+/**
+ * A common parent for [ValueDescriptor] and [NodeDescriptor]. Describes a single [MetaItem] or a group of same-name-siblings.
+ */
 @DFBuilder
-sealed class ItemDescriptor(val config: Config) {
+public sealed class ItemDescriptor(public val config: Config) {
 
     /**
      * True if same name siblings with this name are allowed
-     *
-     * @return
      */
-    var multiple: Boolean by config.boolean(false)
+    public var multiple: Boolean by config.boolean(false)
 
     /**
-     * The item description
-     *
-     * @return
+     * The item description text
      */
-    var info: String? by config.string()
+    public var info: String? by config.string()
 
     /**
      * True if the item is required
-     *
-     * @return
      */
-    abstract var required: Boolean
+    public abstract var required: Boolean
 
 
     /**
@@ -34,29 +31,29 @@ sealed class ItemDescriptor(val config: Config) {
      *
      * @return
      */
-    var attributes by config.node()
-}
+    public var attributes: Config? by config.node()
 
-/**
- * Configure attributes of the descriptor
- */
-fun ItemDescriptor.attributes(block: Config.() -> Unit) {
-    (attributes ?: Config().also { this.attributes = it }).apply(block)
-}
+    /**
+     * An index field by which this node is identified in case of same name siblings construct
+     */
+    public var indexKey: String by config.string(DEFAULT_INDEX_KEY)
 
-/**
- * Set specific attribute in the descriptor
- */
-fun ItemDescriptor.setAttribute(name: Name, value: Any?) {
-    attributes {
-        set(name, value)
+    public companion object{
+        public const val DEFAULT_INDEX_KEY: String = "@index"
     }
 }
 
+/**
+ * Configure attributes of the descriptor, creating an attributes node if needed.
+ */
+public fun ItemDescriptor.attributes(block: Config.() -> Unit) {
+    (attributes ?: Config().also { this.attributes = it }).apply(block)
+}
+
 /**
  * Check if given item suits the descriptor
  */
-fun ItemDescriptor.validateItem(item: MetaItem<*>?): Boolean {
+public fun ItemDescriptor.validateItem(item: MetaItem<*>?): Boolean {
     if (item == null) return !required
     return when (this) {
         is ValueDescriptor -> isAllowedValue(item.value ?: return false)
@@ -73,7 +70,7 @@ fun ItemDescriptor.validateItem(item: MetaItem<*>?): Boolean {
  * @author Alexander Nozik
  */
 @DFBuilder
-class NodeDescriptor(config: Config = Config()) : ItemDescriptor(config) {
+public class NodeDescriptor(config: Config = Config()) : ItemDescriptor(config) {
     init {
         config[IS_NODE_KEY] = true
     }
@@ -90,14 +87,12 @@ class NodeDescriptor(config: Config = Config()) : ItemDescriptor(config) {
      *
      * @return
      */
-    var default by config.node()
+    public var default: Config? by config.node()
 
     /**
-     * An index field by which this node is identified in case of same name siblings construct
+     * The map of children item descriptors (both nodes and values)
      */
-    var indexKey by config.string(DEFAULT_INDEX_KEY)
-
-    val items: Map<String, ItemDescriptor>
+    public val items: Map<String, ItemDescriptor>
         get() = config.getIndexed(ITEM_KEY).mapValues { (_, item) ->
             val node = item.node ?: error("Node descriptor must be a node")
             if (node[IS_NODE_KEY].boolean == true) {
@@ -111,7 +106,7 @@ class NodeDescriptor(config: Config = Config()) : ItemDescriptor(config) {
      * The map of children node descriptors
      */
     @Suppress("UNCHECKED_CAST")
-    val nodes: Map<String, NodeDescriptor>
+    public val nodes: Map<String, NodeDescriptor>
         get() = config.getIndexed(ITEM_KEY).entries.filter {
             it.value.node[IS_NODE_KEY].boolean == true
         }.associate { (name, item) ->
@@ -120,9 +115,9 @@ class NodeDescriptor(config: Config = Config()) : ItemDescriptor(config) {
         }
 
     /**
-     * The list of value descriptors
+     * The list of children value descriptors
      */
-    val values: Map<String, ValueDescriptor>
+    public val values: Map<String, ValueDescriptor>
         get() = config.getIndexed(ITEM_KEY).entries.filter {
             it.value.node[IS_NODE_KEY].boolean != true
         }.associate { (name, item) ->
@@ -141,7 +136,7 @@ class NodeDescriptor(config: Config = Config()) : ItemDescriptor(config) {
                 }
                 NodeDescriptor(config)
             }
-            else -> buildNode(name.first()?.asName()!!).buildNode(name.cutFirst())
+            else -> buildNode(name.firstOrNull()?.asName()!!).buildNode(name.cutFirst())
         }
     }
 
@@ -154,39 +149,43 @@ class NodeDescriptor(config: Config = Config()) : ItemDescriptor(config) {
         config[token] = descriptor.config
     }
 
-    fun item(name: Name, descriptor: ItemDescriptor) {
-        buildNode(name.cutLast()).newItem(name.last().toString(), descriptor)
+    public fun item(name: Name, descriptor: ItemDescriptor) {
+        buildNode(name.cutLast()).newItem(name.lastOrNull().toString(), descriptor)
     }
 
-    fun item(name: String, descriptor: ItemDescriptor) {
+    public fun item(name: String, descriptor: ItemDescriptor) {
         item(name.toName(), descriptor)
     }
 
-    fun node(name: Name, block: NodeDescriptor.() -> Unit) {
+    /**
+     * Create and configure a child node descriptor
+     */
+    public fun node(name: Name, block: NodeDescriptor.() -> Unit) {
         item(name, NodeDescriptor().apply(block))
     }
 
-    fun node(name: String, block: NodeDescriptor.() -> Unit) {
+    public fun node(name: String, block: NodeDescriptor.() -> Unit) {
         node(name.toName(), block)
     }
 
-    fun value(name: Name, block: ValueDescriptor.() -> Unit) {
+    /**
+     * Create and configure child value descriptor
+     */
+    public fun value(name: Name, block: ValueDescriptor.() -> Unit) {
         require(name.length >= 1) { "Name length for value descriptor must be non-empty" }
         item(name, ValueDescriptor().apply(block))
     }
 
-    fun value(name: String, block: ValueDescriptor.() -> Unit) {
+    public fun value(name: String, block: ValueDescriptor.() -> Unit) {
         value(name.toName(), block)
     }
 
-    companion object {
+    public companion object {
 
-        val ITEM_KEY = "item".asName()
-        val IS_NODE_KEY = "@isNode".asName()
+        internal val ITEM_KEY: Name = "item".asName()
+        internal val IS_NODE_KEY: Name = "@isNode".asName()
 
-        const val DEFAULT_INDEX_KEY = "@index"
-
-        inline operator fun invoke(block: NodeDescriptor.() -> Unit) = NodeDescriptor().apply(block)
+        public inline operator fun invoke(block: NodeDescriptor.() -> Unit): NodeDescriptor = NodeDescriptor().apply(block)
 
         //TODO infer descriptor from spec
     }
@@ -195,15 +194,15 @@ class NodeDescriptor(config: Config = Config()) : ItemDescriptor(config) {
 /**
  * Get a descriptor item associated with given name or null if item for given name not provided
  */
-operator fun ItemDescriptor.get(name: Name): ItemDescriptor? {
+public operator fun ItemDescriptor.get(name: Name): ItemDescriptor? {
     if (name.isEmpty()) return this
     return when (this) {
         is ValueDescriptor -> null // empty name already checked
-        is NodeDescriptor -> items[name.first()!!.toString()]?.get(name.cutFirst())
+        is NodeDescriptor -> items[name.firstOrNull()!!.toString()]?.get(name.cutFirst())
     }
 }
 
-operator fun ItemDescriptor.get(name: String): ItemDescriptor? = get(name.toName())
+public operator fun ItemDescriptor.get(name: String): ItemDescriptor? = get(name.toName())
 
 /**
  * A descriptor for meta value
@@ -213,7 +212,7 @@ operator fun ItemDescriptor.get(name: String): ItemDescriptor? = get(name.toName
  * @author Alexander Nozik
  */
 @DFBuilder
-class ValueDescriptor(config: Config = Config()) : ItemDescriptor(config) {
+public class ValueDescriptor(config: Config = Config()) : ItemDescriptor(config) {
 
     /**
      * True if the value is required
@@ -227,9 +226,9 @@ class ValueDescriptor(config: Config = Config()) : ItemDescriptor(config) {
      *
      * @return
      */
-    var default: Value? by config.value()
+    public var default: Value? by config.value()
 
-    fun default(v: Any) {
+    public fun default(v: Any) {
         this.default = Value.of(v)
     }
 
@@ -238,9 +237,9 @@ class ValueDescriptor(config: Config = Config()) : ItemDescriptor(config) {
      *
      * @return
      */
-    var type: List<ValueType>? by config.listValue { ValueType.valueOf(it.string) }
+    public var type: List<ValueType>? by config.listValue { ValueType.valueOf(it.string) }
 
-    fun type(vararg t: ValueType) {
+    public fun type(vararg t: ValueType) {
         this.type = listOf(*t)
     }
 
@@ -251,7 +250,7 @@ class ValueDescriptor(config: Config = Config()) : ItemDescriptor(config) {
      * @param value
      * @return
      */
-    fun isAllowedValue(value: Value): Boolean {
+    public fun isAllowedValue(value: Value): Boolean {
         return (type?.let { it.contains(ValueType.STRING) || it.contains(value.type) } ?: true)
                 && (allowedValues.isEmpty() || allowedValues.contains(value))
     }
@@ -262,7 +261,7 @@ class ValueDescriptor(config: Config = Config()) : ItemDescriptor(config) {
      *
      * @return
      */
-    var allowedValues: List<Value> by config.item().convert(
+    public var allowedValues: List<Value> by config.item().convert(
         reader = {
             val value = it.value
             when {
@@ -279,7 +278,7 @@ class ValueDescriptor(config: Config = Config()) : ItemDescriptor(config) {
     /**
      * Allow given list of value and forbid others
      */
-    fun allow(vararg v: Any) {
+    public fun allow(vararg v: Any) {
         this.allowedValues = v.map { Value.of(it) }
     }
 }
@@ -287,7 +286,7 @@ class ValueDescriptor(config: Config = Config()) : ItemDescriptor(config) {
 /**
  * Merge two node descriptors into one using first one as primary
  */
-operator fun NodeDescriptor.plus(other: NodeDescriptor): NodeDescriptor {
+public operator fun NodeDescriptor.plus(other: NodeDescriptor): NodeDescriptor {
     return NodeDescriptor().apply {
         config.update(other.config)
         config.update(this@plus.config)
diff --git a/dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/getIndexed.kt b/dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/getIndexed.kt
new file mode 100644
index 00000000..20ce93dc
--- /dev/null
+++ b/dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/getIndexed.kt
@@ -0,0 +1,36 @@
+package hep.dataforge.meta
+
+import hep.dataforge.names.*
+
+/**
+ * Get all items matching given name. The index of the last element, if present is used as a [Regex],
+ * against which indexes of elements are matched.
+ */
+public fun Meta.getIndexed(name: Name): Map<String?, MetaItem<*>> {
+    val root = when (name.length) {
+        0 -> error("Can't use empty name for 'getIndexed'")
+        1 -> this
+        else -> this[name.cutLast()].node ?: return emptyMap()
+    }
+
+    val (body, index) = name.lastOrNull()!!
+    return if (index == null) {
+        root.items.filter { it.key.body == body }.mapKeys { it.key.index }
+    } else {
+        val regex = index.toRegex()
+        root.items.filter { it.key.body == body && (regex.matches(it.key.index ?: "")) }
+            .mapKeys { it.key.index }
+    }
+}
+
+public fun Meta.getIndexed(name: String): Map<String?, MetaItem<*>> = this@getIndexed.getIndexed(name.toName())
+
+/**
+ * Get all items matching given name.
+ */
+@Suppress("UNCHECKED_CAST")
+public fun <M : MetaNode<M>> M.getIndexed(name: Name): Map<String, MetaItem<M>> =
+    (this as Meta).getIndexed(name) as Map<String, MetaItem<M>>
+
+public fun <M : MetaNode<M>> M.getIndexed(name: String): Map<String, MetaItem<M>> =
+    getIndexed(name.toName())
\ No newline at end of file
diff --git a/dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/mapMeta.kt b/dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/mapMeta.kt
index ed77f7f0..774a736a 100644
--- a/dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/mapMeta.kt
+++ b/dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/mapMeta.kt
@@ -8,7 +8,7 @@ import hep.dataforge.values.Value
 /**
  * Convert meta to map of maps
  */
-fun Meta.toMap(descriptor: NodeDescriptor? = null): Map<String, Any?> {
+public fun Meta.toMap(descriptor: NodeDescriptor? = null): Map<String, Any?> {
     return items.entries.associate { (token, item) ->
         token.toString() to when (item) {
             is MetaItem.NodeItem -> item.node.toMap()
@@ -22,7 +22,7 @@ fun Meta.toMap(descriptor: NodeDescriptor? = null): Map<String, Any?> {
  * All other values will be converted to values.
  */
 @DFExperimental
-fun Map<String, Any?>.toMeta(descriptor: NodeDescriptor? = null): Meta = Meta {
+public fun Map<String, Any?>.toMeta(descriptor: NodeDescriptor? = null): Meta = Meta {
     @Suppress("UNCHECKED_CAST")
     fun toItem(value: Any?): MetaItem<*> = when (value) {
         is MetaItem<*> -> value
diff --git a/dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/metaMatcher.kt b/dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/metaMatcher.kt
deleted file mode 100644
index f2f747db..00000000
--- a/dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/metaMatcher.kt
+++ /dev/null
@@ -1,35 +0,0 @@
-package hep.dataforge.meta
-
-import hep.dataforge.names.Name
-import hep.dataforge.names.toName
-
-/**
- * Get all items matching given name. The index of the last element, if present is used as a [Regex],
- * against which indexes of elements are matched.
- */
-fun Meta.getIndexed(name: Name): Map<String, MetaItem<*>> {
-    val root = when (name.length) {
-        0 -> error("Can't use empty name for 'getIndexed'")
-        1 -> this
-        else -> this[name.cutLast()].node
-    }
-
-    val (body, index) = name.last()!!
-    val regex = index.toRegex()
-
-    return root?.items
-        ?.filter { it.key.body == body && (index.isEmpty() || regex.matches(it.key.index)) }
-        ?.mapKeys { it.key.index }
-        ?: emptyMap()
-}
-
-fun Meta.getIndexed(name: String): Map<String, MetaItem<*>> = this@getIndexed.getIndexed(name.toName())
-
-/**
- * Get all items matching given name.
- */
-@Suppress("UNCHECKED_CAST")
-fun <M : MetaNode<M>> M.getIndexed(name: Name): Map<String, MetaItem<M>> =
-    (this as Meta).getIndexed(name) as Map<String, MetaItem<M>>
-
-fun <M : MetaNode<M>> M.getIndexed(name: String): Map<String, MetaItem<M>> = getIndexed(name.toName())
\ No newline at end of file
diff --git a/dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/propertyConverter.kt b/dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/propertyConverter.kt
deleted file mode 100644
index ebe55218..00000000
--- a/dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/propertyConverter.kt
+++ /dev/null
@@ -1,83 +0,0 @@
-package hep.dataforge.meta
-
-import hep.dataforge.meta.transformations.MetaConverter
-import kotlin.properties.ReadOnlyProperty
-import kotlin.properties.ReadWriteProperty
-import kotlin.reflect.KProperty
-
-/**
- * Apply a converter to this delegate creating a delegate with a custom type
- */
-fun <R : Any> ItemDelegate.convert(
-    converter: MetaConverter<R>
-): ReadOnlyProperty<Any?, R?> = object : ReadOnlyProperty<Any?, R?> {
-    override fun getValue(thisRef: Any?, property: KProperty<*>): R? =
-        this@convert.getValue(thisRef, property)?.let(converter::itemToObject)
-}
-
-/*
- *
- */
-fun <R : Any> ItemDelegate.convert(
-    converter: MetaConverter<R>,
-    default: () -> R
-): ReadOnlyProperty<Any?, R> = object : ReadOnlyProperty<Any?, R> {
-    override fun getValue(thisRef: Any?, property: KProperty<*>): R =
-        this@convert.getValue(thisRef, property)?.let(converter::itemToObject) ?: default()
-}
-
-/**
- * A converter with a custom reader transformation
- */
-fun <R> ItemDelegate.convert(
-    reader: (MetaItem<*>?) -> R
-): ReadOnlyProperty<Any?, R> = object : ReadOnlyProperty<Any?, R> {
-    override fun getValue(thisRef: Any?, property: KProperty<*>): R =
-        this@convert.getValue(thisRef, property).let(reader)
-}
-
-/*Mutable converters*/
-
-/**
- * A type converter for a mutable [MetaItem] delegate
- */
-fun <R : Any> MutableItemDelegate.convert(
-    converter: MetaConverter<R>
-): ReadWriteProperty<Any?, R?> = object : ReadWriteProperty<Any?, R?> {
-
-    override fun getValue(thisRef: Any?, property: KProperty<*>): R? =
-        this@convert.getValue(thisRef, property)?.let(converter::itemToObject)
-
-    override fun setValue(thisRef: Any?, property: KProperty<*>, value: R?) {
-        val item = value?.let(converter::objectToMetaItem)
-        this@convert.setValue(thisRef, property, item)
-    }
-}
-
-fun <R : Any> MutableItemDelegate.convert(
-    converter: MetaConverter<R>,
-    default: () -> R
-): ReadWriteProperty<Any?, R> = object : ReadWriteProperty<Any?, R> {
-
-    override fun getValue(thisRef: Any?, property: KProperty<*>): R =
-        this@convert.getValue(thisRef, property)?.let(converter::itemToObject) ?: default()
-
-    override fun setValue(thisRef: Any?, property: KProperty<*>, value: R) {
-        val item = value.let(converter::objectToMetaItem)
-        this@convert.setValue(thisRef, property, item)
-    }
-}
-
-fun <R> MutableItemDelegate.convert(
-    reader: (MetaItem<*>?) -> R,
-    writer: (R) -> MetaItem<*>?
-): ReadWriteProperty<Any?, R> = object : ReadWriteProperty<Any?, R> {
-
-    override fun getValue(thisRef: Any?, property: KProperty<*>): R =
-        this@convert.getValue(thisRef, property).let(reader)
-
-    override fun setValue(thisRef: Any?, property: KProperty<*>, value: R) {
-        val item = value?.let(writer)
-        this@convert.setValue(thisRef, property, item)
-    }
-}
diff --git a/dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/serializationUtils.kt b/dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/serializationUtils.kt
deleted file mode 100644
index f06bb06a..00000000
--- a/dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/serializationUtils.kt
+++ /dev/null
@@ -1,72 +0,0 @@
-package hep.dataforge.meta
-
-import kotlinx.serialization.*
-import kotlinx.serialization.builtins.DoubleArraySerializer
-import kotlinx.serialization.builtins.serializer
-import kotlinx.serialization.json.Json
-import kotlinx.serialization.json.JsonConfiguration
-
-fun SerialDescriptorBuilder.boolean(name: String, isOptional: Boolean = false, vararg annotations: Annotation) =
-    element(name, Boolean.serializer().descriptor, isOptional = isOptional, annotations = annotations.toList())
-
-fun SerialDescriptorBuilder.string(name: String, isOptional: Boolean = false, vararg annotations: Annotation) =
-    element(name, String.serializer().descriptor, isOptional = isOptional, annotations = annotations.toList())
-
-fun SerialDescriptorBuilder.int(name: String, isOptional: Boolean = false, vararg annotations: Annotation) =
-    element(name, Int.serializer().descriptor, isOptional = isOptional, annotations = annotations.toList())
-
-fun SerialDescriptorBuilder.double(name: String, isOptional: Boolean = false, vararg annotations: Annotation) =
-    element(name, Double.serializer().descriptor, isOptional = isOptional, annotations = annotations.toList())
-
-fun SerialDescriptorBuilder.float(name: String, isOptional: Boolean = false, vararg annotations: Annotation) =
-    element(name, Float.serializer().descriptor, isOptional = isOptional, annotations = annotations.toList())
-
-fun SerialDescriptorBuilder.long(name: String, isOptional: Boolean = false, vararg annotations: Annotation) =
-    element(name, Long.serializer().descriptor, isOptional = isOptional, annotations = annotations.toList())
-
-fun SerialDescriptorBuilder.doubleArray(name: String, isOptional: Boolean = false, vararg annotations: Annotation) =
-    element(name, DoubleArraySerializer().descriptor, isOptional = isOptional, annotations = annotations.toList())
-
-@OptIn(InternalSerializationApi::class)
-inline fun <reified E : Enum<E>> SerialDescriptorBuilder.enum(
-    name: String,
-    isOptional: Boolean = false,
-    vararg annotations: Annotation
-) {
-    val enumDescriptor = SerialDescriptor(serialName, UnionKind.ENUM_KIND) {
-        enumValues<E>().forEach {
-            val fqn = "$serialName.${it.name}"
-            val enumMemberDescriptor = SerialDescriptor(fqn, StructureKind.OBJECT)
-            element(it.name, enumMemberDescriptor)
-        }
-    }
-    element(name, enumDescriptor, isOptional = isOptional, annotations = annotations.toList())
-}
-
-@DFExperimental
-inline fun <R> Decoder.decodeStructure(
-    desc: SerialDescriptor,
-    vararg typeParams: KSerializer<*> = emptyArray(),
-    crossinline block: CompositeDecoder.() -> R
-): R {
-    val decoder = beginStructure(desc, *typeParams)
-    val res = decoder.block()
-    decoder.endStructure(desc)
-    return res
-}
-
-@DFExperimental
-inline fun Encoder.encodeStructure(
-    desc: SerialDescriptor,
-    vararg typeParams: KSerializer<*> = emptyArray(),
-    block: CompositeEncoder.() -> Unit
-) {
-    val encoder = beginStructure(desc, *typeParams)
-    encoder.block()
-    encoder.endStructure(desc)
-}
-
-@OptIn(UnstableDefault::class)
-val JSON_PRETTY = Json(JsonConfiguration(prettyPrint = true, useArrayPolymorphism = true))
-@OptIn(UnstableDefault::class)
-val JSON_PLAIN = Json(JsonConfiguration(prettyPrint = true, useArrayPolymorphism = true))
\ No newline at end of file
diff --git a/dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/transformations/MetaConverter.kt b/dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/transformations/MetaConverter.kt
index 931e7cf3..0e4d6261 100644
--- a/dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/transformations/MetaConverter.kt
+++ b/dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/transformations/MetaConverter.kt
@@ -6,18 +6,18 @@ import hep.dataforge.values.*
 /**
  * A converter of generic object to and from [MetaItem]
  */
-interface MetaConverter<T : Any> {
-    fun itemToObject(item: MetaItem<*>): T
-    fun objectToMetaItem(obj: T): MetaItem<*>
+public interface MetaConverter<T : Any> {
+    public fun itemToObject(item: MetaItem<*>): T
+    public fun objectToMetaItem(obj: T): MetaItem<*>
 
-    companion object {
+    public companion object {
 
-        val item = object : MetaConverter<MetaItem<*>> {
+        public val item: MetaConverter<MetaItem<*>> = object : MetaConverter<MetaItem<*>> {
             override fun itemToObject(item: MetaItem<*>): MetaItem<*> = item
             override fun objectToMetaItem(obj: MetaItem<*>): MetaItem<*> = obj
         }
 
-        val meta = object : MetaConverter<Meta> {
+        public val meta: MetaConverter<Meta> = object : MetaConverter<Meta> {
             override fun itemToObject(item: MetaItem<*>): Meta = when (item) {
                 is MetaItem.NodeItem -> item.node
                 is MetaItem.ValueItem -> item.value.toMeta()
@@ -26,7 +26,7 @@ interface MetaConverter<T : Any> {
             override fun objectToMetaItem(obj: Meta): MetaItem<*> = MetaItem.NodeItem(obj)
         }
 
-        val value = object : MetaConverter<Value> {
+        public val value: MetaConverter<Value> = object : MetaConverter<Value> {
             override fun itemToObject(item: MetaItem<*>): Value = when (item) {
                 is MetaItem.NodeItem -> item.node[Meta.VALUE_KEY].value ?: error("Can't convert node to a value")
                 is MetaItem.ValueItem -> item.value
@@ -35,7 +35,7 @@ interface MetaConverter<T : Any> {
             override fun objectToMetaItem(obj: Value): MetaItem<*> = MetaItem.ValueItem(obj)
         }
 
-        val string = object : MetaConverter<String> {
+        public val string: MetaConverter<String> = object : MetaConverter<String> {
             override fun itemToObject(item: MetaItem<*>): String = when (item) {
                 is MetaItem.NodeItem -> item.node[Meta.VALUE_KEY].value ?: error("Can't convert node to a value")
                 is MetaItem.ValueItem -> item.value
@@ -44,7 +44,7 @@ interface MetaConverter<T : Any> {
             override fun objectToMetaItem(obj: String): MetaItem<*> = MetaItem.ValueItem(obj.asValue())
         }
 
-        val boolean = object : MetaConverter<Boolean> {
+        public val boolean: MetaConverter<Boolean> = object : MetaConverter<Boolean> {
             override fun itemToObject(item: MetaItem<*>): Boolean = when (item) {
                 is MetaItem.NodeItem -> item.node[Meta.VALUE_KEY].value ?: error("Can't convert node to a value")
                 is MetaItem.ValueItem -> item.value
@@ -53,7 +53,7 @@ interface MetaConverter<T : Any> {
             override fun objectToMetaItem(obj: Boolean): MetaItem<*> = MetaItem.ValueItem(obj.asValue())
         }
 
-        val number = object : MetaConverter<Number> {
+        public val number: MetaConverter<Number> = object : MetaConverter<Number> {
             override fun itemToObject(item: MetaItem<*>): Number = when (item) {
                 is MetaItem.NodeItem -> item.node[Meta.VALUE_KEY].value ?: error("Can't convert node to a value")
                 is MetaItem.ValueItem -> item.value
@@ -62,7 +62,7 @@ interface MetaConverter<T : Any> {
             override fun objectToMetaItem(obj: Number): MetaItem<*> = MetaItem.ValueItem(obj.asValue())
         }
 
-        val double = object : MetaConverter<Double> {
+        public val double: MetaConverter<Double> = object : MetaConverter<Double> {
             override fun itemToObject(item: MetaItem<*>): Double = when (item) {
                 is MetaItem.NodeItem -> item.node[Meta.VALUE_KEY].value ?: error("Can't convert node to a value")
                 is MetaItem.ValueItem -> item.value
@@ -71,7 +71,7 @@ interface MetaConverter<T : Any> {
             override fun objectToMetaItem(obj: Double): MetaItem<*> = MetaItem.ValueItem(obj.asValue())
         }
 
-        val float = object : MetaConverter<Float> {
+        public val float: MetaConverter<Float> = object : MetaConverter<Float> {
             override fun itemToObject(item: MetaItem<*>): Float = when (item) {
                 is MetaItem.NodeItem -> item.node[Meta.VALUE_KEY].value ?: error("Can't convert node to a value")
                 is MetaItem.ValueItem -> item.value
@@ -80,7 +80,7 @@ interface MetaConverter<T : Any> {
             override fun objectToMetaItem(obj: Float): MetaItem<*> = MetaItem.ValueItem(obj.asValue())
         }
 
-        val int = object : MetaConverter<Int> {
+        public val int: MetaConverter<Int> = object : MetaConverter<Int> {
             override fun itemToObject(item: MetaItem<*>): Int = when (item) {
                 is MetaItem.NodeItem -> item.node[Meta.VALUE_KEY].value ?: error("Can't convert node to a value")
                 is MetaItem.ValueItem -> item.value
@@ -89,7 +89,7 @@ interface MetaConverter<T : Any> {
             override fun objectToMetaItem(obj: Int): MetaItem<*> = MetaItem.ValueItem(obj.asValue())
         }
 
-        val long = object : MetaConverter<Long> {
+        public val long: MetaConverter<Long> = object : MetaConverter<Long> {
             override fun itemToObject(item: MetaItem<*>): Long = when (item) {
                 is MetaItem.NodeItem -> item.node[Meta.VALUE_KEY].value ?: error("Can't convert node to a value")
                 is MetaItem.ValueItem -> item.value
@@ -98,14 +98,14 @@ interface MetaConverter<T : Any> {
             override fun objectToMetaItem(obj: Long): MetaItem<*> = MetaItem.ValueItem(obj.asValue())
         }
 
-        inline fun <reified E : Enum<E>> enum(): MetaConverter<E> = object : MetaConverter<E> {
+        public inline fun <reified E : Enum<E>> enum(): MetaConverter<E> = object : MetaConverter<E> {
             @Suppress("USELESS_CAST")
             override fun itemToObject(item: MetaItem<*>): E = item.enum<E>() as? E ?: error("The Item is not a Enum")
 
             override fun objectToMetaItem(obj: E): MetaItem<*> = MetaItem.ValueItem(obj.asValue())
         }
 
-        fun <T> valueList(writer: (T) -> Value = {Value.of(it)}, reader: (Value) -> T): MetaConverter<List<T>> =
+        public fun <T> valueList(writer: (T) -> Value = {Value.of(it)}, reader: (Value) -> T): MetaConverter<List<T>> =
             object : MetaConverter<List<T>> {
                 override fun itemToObject(item: MetaItem<*>): List<T> =
                     item.value?.list?.map(reader) ?: error("The item is not a value list")
@@ -117,8 +117,8 @@ interface MetaConverter<T : Any> {
     }
 }
 
-fun <T : Any> MetaConverter<T>.nullableItemToObject(item: MetaItem<*>?): T? = item?.let { itemToObject(it) }
-fun <T : Any> MetaConverter<T>.nullableObjectToMetaItem(obj: T?): MetaItem<*>? = obj?.let { objectToMetaItem(it) }
+public fun <T : Any> MetaConverter<T>.nullableItemToObject(item: MetaItem<*>?): T? = item?.let { itemToObject(it) }
+public fun <T : Any> MetaConverter<T>.nullableObjectToMetaItem(obj: T?): MetaItem<*>? = obj?.let { objectToMetaItem(it) }
 
-fun <T : Any> MetaConverter<T>.metaToObject(meta: Meta): T = itemToObject(MetaItem.NodeItem(meta))
-fun <T : Any> MetaConverter<T>.valueToObject(value: Value): T = itemToObject(MetaItem.ValueItem(value))
+public fun <T : Any> MetaConverter<T>.metaToObject(meta: Meta): T = itemToObject(MetaItem.NodeItem(meta))
+public fun <T : Any> MetaConverter<T>.valueToObject(value: Value): T = itemToObject(MetaItem.ValueItem(value))
diff --git a/dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/transformations/MetaTransformation.kt b/dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/transformations/MetaTransformation.kt
index 38984520..9529b28e 100644
--- a/dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/transformations/MetaTransformation.kt
+++ b/dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/transformations/MetaTransformation.kt
@@ -6,31 +6,31 @@ import hep.dataforge.names.Name
 /**
  * A transformation for meta item or a group of items
  */
-interface TransformationRule {
+public interface TransformationRule {
 
     /**
      * Check if this transformation should be applied to a node with given name and value
      */
-    fun matches(name: Name, item: MetaItem<*>?): Boolean
+    public fun matches(name: Name, item: MetaItem<*>?): Boolean
 
     /**
      * Select all items to be transformed. Item could be a value as well as node
      *
      * @return a sequence of item paths to be transformed
      */
-    fun selectItems(meta: Meta): Sequence<Name> =
+    public fun selectItems(meta: Meta): Sequence<Name> =
         meta.sequence().filter { matches(it.first, it.second) }.map { it.first }
 
     /**
      * Apply transformation for a single item (Node or Value) to the target
      */
-    fun <M : MutableMeta<M>> transformItem(name: Name, item: MetaItem<*>?, target: M): Unit
+    public fun <M : MutableMeta<M>> transformItem(name: Name, item: MetaItem<*>?, target: M): Unit
 }
 
 /**
  * A transformation which keeps all elements, matching [selector] unchanged.
  */
-data class KeepTransformationRule(val selector: (Name) -> Boolean) :
+public data class KeepTransformationRule(val selector: (Name) -> Boolean) :
     TransformationRule {
     override fun matches(name: Name, item: MetaItem<*>?): Boolean {
         return selector(name)
@@ -47,7 +47,7 @@ data class KeepTransformationRule(val selector: (Name) -> Boolean) :
 /**
  * A transformation which transforms element with specific name
  */
-data class SingleItemTransformationRule(
+public data class SingleItemTransformationRule(
     val from: Name,
     val transform: MutableMeta<*>.(Name, MetaItem<*>?) -> Unit
 ) : TransformationRule {
@@ -64,7 +64,7 @@ data class SingleItemTransformationRule(
     }
 }
 
-data class RegexItemTransformationRule(
+public data class RegexItemTransformationRule(
     val from: Regex,
     val transform: MutableMeta<*>.(name: Name, MatchResult, MetaItem<*>?) -> Unit
 ) : TransformationRule {
@@ -84,12 +84,12 @@ data class RegexItemTransformationRule(
 /**
  * A set of [TransformationRule] to either transform static meta or create dynamically updated [MutableMeta]
  */
-inline class MetaTransformation(val transformations: Collection<TransformationRule>) {
+public inline class MetaTransformation(public val transformations: Collection<TransformationRule>) {
 
     /**
      * Produce new meta using only those items that match transformation rules
      */
-    fun generate(source: Meta): Meta =
+    public fun generate(source: Meta): Meta =
         Meta {
             transformations.forEach { rule ->
                 rule.selectItems(source).forEach { name ->
@@ -102,7 +102,7 @@ inline class MetaTransformation(val transformations: Collection<TransformationRu
      * Generate an observable configuration that contains only elements defined by transformation rules and changes with the source
      */
     @DFExperimental
-    fun generate(source: Config): ObservableMeta = Config().apply {
+    public fun generate(source: Config): ObservableMeta = Config().apply {
         transformations.forEach { rule ->
             rule.selectItems(source).forEach { name ->
                 rule.transformItem(name, source[name], this)
@@ -115,7 +115,7 @@ inline class MetaTransformation(val transformations: Collection<TransformationRu
     /**
      * Transform a meta, replacing all elements found in rules with transformed entries
      */
-    fun apply(source: Meta): Meta =
+    public fun apply(source: Meta): Meta =
         source.edit {
             transformations.forEach { rule ->
                 rule.selectItems(source).forEach { name ->
@@ -128,7 +128,7 @@ inline class MetaTransformation(val transformations: Collection<TransformationRu
     /**
      * Listens for changes in the source node and translates them into second node if transformation set contains a corresponding rule.
      */
-    fun <M : MutableMeta<M>> bind(source: Config, target: M) {
+    public fun <M : MutableMeta<M>> bind(source: Config, target: M) {
         source.onChange(target) { name, _, newItem ->
             transformations.forEach { t ->
                 if (t.matches(name, newItem)) {
@@ -138,8 +138,8 @@ inline class MetaTransformation(val transformations: Collection<TransformationRu
         }
     }
 
-    companion object {
-        fun make(block: MetaTransformationBuilder.() -> Unit): MetaTransformation =
+    public companion object {
+        public fun make(block: MetaTransformationBuilder.() -> Unit): MetaTransformation =
             MetaTransformationBuilder().apply(block).build()
     }
 }
@@ -147,27 +147,27 @@ inline class MetaTransformation(val transformations: Collection<TransformationRu
 /**
  * A builder for a set of transformation rules
  */
-class MetaTransformationBuilder {
-    val transformations = HashSet<TransformationRule>()
+public class MetaTransformationBuilder {
+    private val transformations = HashSet<TransformationRule>()
 
     /**
      * Keep all items with name satisfying the criteria
      */
-    fun keep(selector: (Name) -> Boolean) {
+    public fun keep(selector: (Name) -> Boolean) {
         transformations.add(KeepTransformationRule(selector))
     }
 
     /**
      * Keep specific item (including its descendants)
      */
-    fun keep(name: Name) {
+    public fun keep(name: Name) {
         keep { it == name }
     }
 
     /**
      * Keep nodes by regex
      */
-    fun keep(regex: String) {
+    public fun keep(regex: String) {
         transformations.add(
             RegexItemTransformationRule(regex.toRegex()) { name, _, metaItem ->
                 setItem(name, metaItem)
@@ -177,7 +177,7 @@ class MetaTransformationBuilder {
     /**
      * Move an item from [from] to [to], optionally applying [operation] it defined
      */
-    fun move(from: Name, to: Name, operation: (MetaItem<*>?) -> Any? = { it }) {
+    public fun move(from: Name, to: Name, operation: (MetaItem<*>?) -> Any? = { it }) {
         transformations.add(
             SingleItemTransformationRule(from) { _, item ->
                 set(to, operation(item))
@@ -185,5 +185,5 @@ class MetaTransformationBuilder {
         )
     }
 
-    fun build() = MetaTransformation(transformations)
+    public fun build(): MetaTransformation = MetaTransformation(transformations)
 }
\ No newline at end of file
diff --git a/dataforge-meta/src/commonMain/kotlin/hep/dataforge/names/Name.kt b/dataforge-meta/src/commonMain/kotlin/hep/dataforge/names/Name.kt
index b3f8231a..9cce4314 100644
--- a/dataforge-meta/src/commonMain/kotlin/hep/dataforge/names/Name.kt
+++ b/dataforge-meta/src/commonMain/kotlin/hep/dataforge/names/Name.kt
@@ -1,6 +1,12 @@
 package hep.dataforge.names
 
-import kotlinx.serialization.*
+import kotlinx.serialization.KSerializer
+import kotlinx.serialization.Serializable
+import kotlinx.serialization.descriptors.PrimitiveKind
+import kotlinx.serialization.descriptors.PrimitiveSerialDescriptor
+import kotlinx.serialization.descriptors.SerialDescriptor
+import kotlinx.serialization.encoding.Decoder
+import kotlinx.serialization.encoding.Encoder
 
 
 /**
@@ -8,32 +14,9 @@ import kotlinx.serialization.*
  * The name is a dot separated list of strings like `token1.token2.token3`.
  * Each token could contain additional index in square brackets.
  */
-@Serializable
-class Name(val tokens: List<NameToken>) {
-
-    val length get() = tokens.size
-
-    /**
-     * First token of the name or null if it is empty
-     */
-    fun first(): NameToken? = tokens.firstOrNull()
-
-    /**
-     * Last token of the name or null if it is empty
-     */
-    fun last(): NameToken? = tokens.lastOrNull()
-
-    /**
-     * The reminder of the name after first element is cut. For empty name return itself.
-     */
-    fun cutFirst(): Name = Name(tokens.drop(1))
-
-    /**
-     * The reminder of the name after last element is cut. For empty name return itself.
-     */
-    fun cutLast(): Name = Name(tokens.dropLast(1))
-
-    operator fun get(i: Int): NameToken = tokens[i]
+@Serializable(Name.Companion::class)
+public class Name(public val tokens: List<NameToken>) {
+    //TODO to be transformed into inline class after they are supported with serialization
 
     override fun toString(): String = tokens.joinToString(separator = NAME_SEPARATOR) { it.toString() }
 
@@ -53,14 +36,13 @@ class Name(val tokens: List<NameToken>) {
         }
     }
 
-    @Serializer(Name::class)
-    companion object : KSerializer<Name> {
-        const val NAME_SEPARATOR = "."
+    public companion object : KSerializer<Name> {
+        public const val NAME_SEPARATOR: String = "."
 
-        val EMPTY = Name(emptyList())
+        public val EMPTY: Name = Name(emptyList())
 
         override val descriptor: SerialDescriptor =
-            PrimitiveDescriptor("hep.dataforge.names.Name", PrimitiveKind.STRING)
+            PrimitiveSerialDescriptor("hep.dataforge.names.Name", PrimitiveKind.STRING)
 
         override fun deserialize(decoder: Decoder): Name {
             return decoder.decodeString().toName()
@@ -72,54 +54,36 @@ class Name(val tokens: List<NameToken>) {
     }
 }
 
+public operator fun Name.get(i: Int): NameToken = tokens[i]
+
 /**
- * A single name token. Body is not allowed to be empty.
- * Following symbols are prohibited in name tokens: `{}.:\`.
- * A name token could have appendix in square brackets called *index*
+ * The reminder of the name after last element is cut. For empty name return itself.
  */
-@Serializable
-data class NameToken(val body: String, val index: String = "") {
+public fun Name.cutLast(): Name = Name(tokens.dropLast(1))
 
-    init {
-        if (body.isEmpty()) error("Syntax error: Name token body is empty")
-    }
+/**
+ * The reminder of the name after first element is cut. For empty name return itself.
+ */
+public fun Name.cutFirst(): Name = Name(tokens.drop(1))
 
-    private fun String.escape() =
-        replace("\\", "\\\\")
-            .replace(".", "\\.")
-            .replace("[", "\\[")
-            .replace("]", "\\]")
+public val Name.length: Int get() = tokens.size
 
-    override fun toString(): String = if (hasIndex()) {
-        "${body.escape()}[$index]"
-    } else {
-        body.escape()
-    }
+/**
+ * Last token of the name or null if it is empty
+ */
+public fun Name.lastOrNull(): NameToken? = tokens.lastOrNull()
 
-    fun hasIndex() = index.isNotEmpty()
+/**
+ * First token of the name or null if it is empty
+ */
+public fun Name.firstOrNull(): NameToken? = tokens.firstOrNull()
 
-    @Serializer(NameToken::class)
-    companion object : KSerializer<NameToken> {
-        override val descriptor: SerialDescriptor =
-            PrimitiveDescriptor("hep.dataforge.names.NameToken", PrimitiveKind.STRING)
-
-        override fun deserialize(decoder: Decoder): NameToken {
-            return decoder.decodeString().toName().first()!!
-        }
-
-        override fun serialize(encoder: Encoder, value: NameToken) {
-            encoder.encodeString(value.toString())
-        }
-    }
-}
-
-fun NameToken.withIndex(newIndex: String) = NameToken(body, newIndex)
 
 /**
  * Convert a [String] to name parsing it and extracting name tokens and index syntax.
  * This operation is rather heavy so it should be used with care in high performance code.
  */
-fun String.toName(): Name {
+public fun String.toName(): Name {
     if (isBlank()) return Name.EMPTY
     val tokens = sequence {
         var bodyBuilder = StringBuilder()
@@ -150,7 +114,8 @@ fun String.toName(): Name {
                 }
                 else -> when (it) {
                     '.' -> {
-                        yield(NameToken(bodyBuilder.toString(), queryBuilder.toString()))
+                        val query = if(queryBuilder.isEmpty()) null else queryBuilder.toString()
+                        yield(NameToken(bodyBuilder.toString(), query))
                         bodyBuilder = StringBuilder()
                         queryBuilder = StringBuilder()
                     }
@@ -163,7 +128,8 @@ fun String.toName(): Name {
                 }
             }
         }
-        yield(NameToken(bodyBuilder.toString(), queryBuilder.toString()))
+        val query = if(queryBuilder.isEmpty()) null else queryBuilder.toString()
+        yield(NameToken(bodyBuilder.toString(), query))
     }
     return Name(tokens.toList())
 }
@@ -172,26 +138,26 @@ fun String.toName(): Name {
  * Convert the [String] to a [Name] by simply wrapping it in a single name token without parsing.
  * The input string could contain dots and braces, but they are just escaped, not parsed.
  */
-fun String.asName(): Name = if (isBlank()) Name.EMPTY else NameToken(this).asName()
+public fun String.asName(): Name = if (isBlank()) Name.EMPTY else NameToken(this).asName()
 
-operator fun NameToken.plus(other: Name): Name = Name(listOf(this) + other.tokens)
+public operator fun NameToken.plus(other: Name): Name = Name(listOf(this) + other.tokens)
 
-operator fun Name.plus(other: Name): Name = Name(this.tokens + other.tokens)
+public operator fun Name.plus(other: Name): Name = Name(this.tokens + other.tokens)
 
-operator fun Name.plus(other: String): Name = this + other.toName()
+public operator fun Name.plus(other: String): Name = this + other.toName()
 
-operator fun Name.plus(other: NameToken): Name = Name(tokens + other)
+public operator fun Name.plus(other: NameToken): Name = Name(tokens + other)
 
-fun Name.appendLeft(other: String): Name = NameToken(other) + this
+public fun Name.appendLeft(other: String): Name = NameToken(other) + this
 
-fun NameToken.asName() = Name(listOf(this))
+public fun NameToken.asName(): Name = Name(listOf(this))
 
-fun Name.isEmpty(): Boolean = this.length == 0
+public fun Name.isEmpty(): Boolean = this.length == 0
 
 /**
  * Set or replace last token index
  */
-fun Name.withIndex(index: String): Name {
+public fun Name.withIndex(index: String): Name {
     val last = NameToken(tokens.last().body, index)
     if (length == 0) error("Can't add index to empty name")
     if (length == 1) {
@@ -206,19 +172,19 @@ fun Name.withIndex(index: String): Name {
 /**
  * Fast [String]-based accessor for item map
  */
-operator fun <T> Map<NameToken, T>.get(body: String, query: String = ""): T? = get(NameToken(body, query))
+public operator fun <T> Map<NameToken, T>.get(body: String, query: String? = null): T? = get(NameToken(body, query))
 
-operator fun <T> Map<Name, T>.get(name: String) = get(name.toName())
-operator fun <T> MutableMap<Name, T>.set(name: String, value: T) = set(name.toName(), value)
+public operator fun <T> Map<Name, T>.get(name: String): T? = get(name.toName())
+public operator fun <T> MutableMap<Name, T>.set(name: String, value: T): Unit = set(name.toName(), value)
 
 /* Name comparison operations */
 
-fun Name.startsWith(token: NameToken): Boolean = first() == token
+public fun Name.startsWith(token: NameToken): Boolean = firstOrNull() == token
 
-fun Name.endsWith(token: NameToken): Boolean = last() == token
+public fun Name.endsWith(token: NameToken): Boolean = lastOrNull() == token
 
-fun Name.startsWith(name: Name): Boolean =
+public fun Name.startsWith(name: Name): Boolean =
     this.length >= name.length && tokens.subList(0, name.length) == name.tokens
 
-fun Name.endsWith(name: Name): Boolean =
+public fun Name.endsWith(name: Name): Boolean =
     this.length >= name.length && tokens.subList(length - name.length, length) == name.tokens
\ No newline at end of file
diff --git a/dataforge-meta/src/commonMain/kotlin/hep/dataforge/names/NameToken.kt b/dataforge-meta/src/commonMain/kotlin/hep/dataforge/names/NameToken.kt
new file mode 100644
index 00000000..d010ac5a
--- /dev/null
+++ b/dataforge-meta/src/commonMain/kotlin/hep/dataforge/names/NameToken.kt
@@ -0,0 +1,60 @@
+package hep.dataforge.names
+
+import kotlinx.serialization.KSerializer
+import kotlinx.serialization.Serializable
+import kotlinx.serialization.descriptors.PrimitiveKind
+import kotlinx.serialization.descriptors.PrimitiveSerialDescriptor
+import kotlinx.serialization.descriptors.SerialDescriptor
+import kotlinx.serialization.encoding.Decoder
+import kotlinx.serialization.encoding.Encoder
+
+/**
+ * A single name token. Body is not allowed to be empty.
+ * Following symbols are prohibited in name tokens: `{}.:\`.
+ * A name token could have appendix in square brackets called *index*
+ */
+@Serializable(NameToken.Companion::class)
+public data class NameToken(val body: String, val index: String? = null) {
+
+    init {
+        if (body.isEmpty()) error("Syntax error: Name token body is empty")
+    }
+
+    private fun String.escape() =
+        replace("\\", "\\\\")
+            .replace(".", "\\.")
+            .replace("[", "\\[")
+            .replace("]", "\\]")
+
+    override fun toString(): String = if (hasIndex()) {
+        "${body.escape()}[$index]"
+    } else {
+        body.escape()
+    }
+
+    public companion object : KSerializer<NameToken> {
+        override val descriptor: SerialDescriptor =
+            PrimitiveSerialDescriptor("hep.dataforge.names.NameToken", PrimitiveKind.STRING)
+
+        override fun deserialize(decoder: Decoder): NameToken {
+            return decoder.decodeString().toName().firstOrNull()!!
+        }
+
+        override fun serialize(
+            encoder: Encoder,
+            value: NameToken,
+        ) {
+            encoder.encodeString(value.toString())
+        }
+    }
+}
+
+/**
+ * Check if index is defined for this token
+ */
+public fun NameToken.hasIndex(): Boolean = index != null
+
+/**
+ * Add or replace index part of this token
+ */
+public fun NameToken.withIndex(newIndex: String): NameToken = NameToken(body, newIndex)
diff --git a/dataforge-meta/src/commonMain/kotlin/hep/dataforge/values/Value.kt b/dataforge-meta/src/commonMain/kotlin/hep/dataforge/values/Value.kt
index 05c082e9..ca78f0ae 100644
--- a/dataforge-meta/src/commonMain/kotlin/hep/dataforge/values/Value.kt
+++ b/dataforge-meta/src/commonMain/kotlin/hep/dataforge/values/Value.kt
@@ -10,7 +10,7 @@ import kotlinx.serialization.Serializable
  *
  */
 @Serializable
-enum class ValueType {
+public enum class ValueType {
     NUMBER, STRING, BOOLEAN, NULL
 }
 
@@ -19,44 +19,44 @@ enum class ValueType {
  *
  * Value can represent a list of value objects.
  */
-interface Value {
+@Serializable(ValueSerializer::class)
+public interface Value {
     /**
      * Get raw value of this value
      */
-    val value: Any?
+    public val value: Any?
 
     /**
      * The type of the value
      */
-    val type: ValueType
+    public val type: ValueType
 
     /**
      * get this value represented as Number
      */
-    val number: Number
+    public val number: Number
 
     /**
      * get this value represented as String
      */
-    val string: String
+    public val string: String
 
     /**
      * get this value represented as List
      */
-    val list: List<Value>
-        get() = if (this == Null) emptyList() else listOf(this)
+    public val list: List<Value> get() = if (this == Null) emptyList() else listOf(this)
 
     override fun equals(other: Any?): Boolean
 
     override fun hashCode(): Int
 
-    companion object {
-        const val TYPE = "value"
+    public companion object {
+        public const val TARGET: String = "value"
 
         /**
          * Convert object to value
          */
-        fun of(value: Any?): Value {
+        public fun of(value: Any?): Value {
             return when (value) {
                 null -> Null
                 is Value -> value
@@ -89,7 +89,7 @@ interface Value {
 /**
  * A singleton null value
  */
-object Null : Value {
+public object Null : Value {
     override val value: Any? get() = null
     override val type: ValueType get() = ValueType.NULL
     override val number: Number get() = Double.NaN
@@ -104,7 +104,7 @@ object Null : Value {
 /**
  * Singleton true value
  */
-object True : Value {
+public object True : Value {
     override val value: Any? get() = true
     override val type: ValueType get() = ValueType.BOOLEAN
     override val number: Number get() = 1.0
@@ -119,7 +119,7 @@ object True : Value {
 /**
  * Singleton false value
  */
-object False : Value {
+public object False : Value {
     override val value: Any? get() = false
     override val type: ValueType get() = ValueType.BOOLEAN
     override val number: Number get() = -1.0
@@ -131,7 +131,7 @@ object False : Value {
     override fun hashCode(): Int = -1
 }
 
-class NumberValue(override val number: Number) : Value {
+public class NumberValue(override val number: Number) : Value {
     override val value: Any? get() = number
     override val type: ValueType get() = ValueType.NUMBER
     override val string: String get() = number.toString()
@@ -154,7 +154,7 @@ class NumberValue(override val number: Number) : Value {
     override fun toString(): String = value.toString()
 }
 
-class StringValue(override val string: String) : Value {
+public class StringValue(override val string: String) : Value {
     override val value: Any? get() = string
     override val type: ValueType get() = ValueType.STRING
     override val number: Number get() = string.toDouble()
@@ -168,7 +168,7 @@ class StringValue(override val string: String) : Value {
     override fun toString(): String = "\"${value.toString()}\""
 }
 
-class EnumValue<E : Enum<*>>(override val value: E) : Value {
+public class EnumValue<E : Enum<*>>(override val value: E) : Value {
     override val type: ValueType get() = ValueType.STRING
     override val number: Number get() = value.ordinal
     override val string: String get() = value.name
@@ -182,7 +182,7 @@ class EnumValue<E : Enum<*>>(override val value: E) : Value {
     override fun toString(): String = value.toString()
 }
 
-class ListValue(override val list: List<Value>) : Value {
+public class ListValue(override val list: List<Value>) : Value {
     init {
         require(list.isNotEmpty()) { "Can't create list value from empty list" }
     }
@@ -210,34 +210,34 @@ class ListValue(override val list: List<Value>) : Value {
 
 }
 
-fun Number.asValue(): Value = NumberValue(this)
+public fun Number.asValue(): Value = NumberValue(this)
 
-fun Boolean.asValue(): Value = if (this) True else False
+public fun Boolean.asValue(): Value = if (this) True else False
 
-fun String.asValue(): Value = StringValue(this)
+public fun String.asValue(): Value = StringValue(this)
 
-fun Iterable<Value>.asValue(): Value {
+public fun Iterable<Value>.asValue(): Value {
     val list = toList()
     return if (list.isEmpty()) Null else ListValue(this.toList())
 }
 
-fun IntArray.asValue(): Value = if (isEmpty()) Null else ListValue(map { NumberValue(it) })
+public fun IntArray.asValue(): Value = if (isEmpty()) Null else ListValue(map { NumberValue(it) })
 
-fun LongArray.asValue(): Value = if (isEmpty()) Null else ListValue(map { NumberValue(it) })
+public fun LongArray.asValue(): Value = if (isEmpty()) Null else ListValue(map { NumberValue(it) })
 
-fun ShortArray.asValue(): Value = if (isEmpty()) Null else ListValue(map { NumberValue(it) })
+public fun ShortArray.asValue(): Value = if (isEmpty()) Null else ListValue(map { NumberValue(it) })
 
-fun FloatArray.asValue(): Value = if (isEmpty()) Null else ListValue(map { NumberValue(it) })
+public fun FloatArray.asValue(): Value = if (isEmpty()) Null else ListValue(map { NumberValue(it) })
 
-fun ByteArray.asValue(): Value = if (isEmpty()) Null else ListValue(map { NumberValue(it) })
+public fun ByteArray.asValue(): Value = if (isEmpty()) Null else ListValue(map { NumberValue(it) })
 
-fun <E : Enum<E>> E.asValue(): Value = EnumValue(this)
+public fun <E : Enum<E>> E.asValue(): Value = EnumValue(this)
 
 
 /**
  * Create Value from String using closest match conversion
  */
-fun String.parseValue(): Value {
+public fun String.parseValue(): Value {
 
     //Trying to get integer
     if (isEmpty() || this == Null.string) {
diff --git a/dataforge-meta/src/commonMain/kotlin/hep/dataforge/values/ValueSerializer.kt b/dataforge-meta/src/commonMain/kotlin/hep/dataforge/values/ValueSerializer.kt
index 8055b554..08b87c18 100644
--- a/dataforge-meta/src/commonMain/kotlin/hep/dataforge/values/ValueSerializer.kt
+++ b/dataforge-meta/src/commonMain/kotlin/hep/dataforge/values/ValueSerializer.kt
@@ -1,24 +1,25 @@
 package hep.dataforge.values
 
-import hep.dataforge.meta.boolean
-import hep.dataforge.meta.enum
-import hep.dataforge.meta.string
-import kotlinx.serialization.*
-import kotlinx.serialization.builtins.list
+import kotlinx.serialization.KSerializer
+import kotlinx.serialization.builtins.ListSerializer
+import kotlinx.serialization.descriptors.SerialDescriptor
+import kotlinx.serialization.descriptors.buildClassSerialDescriptor
+import kotlinx.serialization.descriptors.element
+import kotlinx.serialization.encoding.Decoder
+import kotlinx.serialization.encoding.Encoder
 
-@Serializer(Value::class)
-object ValueSerializer : KSerializer<Value> {
-    private val listSerializer by lazy { ValueSerializer.list }
+public object ValueSerializer : KSerializer<Value> {
+    private val listSerializer by lazy { ListSerializer(ValueSerializer) }
 
     override val descriptor: SerialDescriptor =
-        SerialDescriptor("hep.dataforge.values.Value") {
-            boolean("isList")
-            enum<ValueType>("valueType")
-            string("value")
+        buildClassSerialDescriptor("hep.dataforge.values.Value") {
+            element<Boolean>("isList")
+            element<ValueType>("valueType")
+            element<String>("value")
         }
 
     private fun Decoder.decodeValue(): Value {
-        return when (decode(ValueType.serializer())) {
+        return when (decodeSerializableValue(ValueType.serializer())) {
             ValueType.NULL -> Null
             ValueType.NUMBER -> decodeDouble().asValue() //TODO differentiate?
             ValueType.BOOLEAN -> decodeBoolean().asValue()
@@ -37,7 +38,7 @@ object ValueSerializer : KSerializer<Value> {
     }
 
     private fun Encoder.encodeValue(value: Value) {
-        encode(ValueType.serializer(), value.type)
+        encodeSerializableValue(ValueType.serializer(), value.type)
         when (value.type) {
             ValueType.NULL -> {
                 // do nothing
diff --git a/dataforge-meta/src/commonMain/kotlin/hep/dataforge/values/exoticValues.kt b/dataforge-meta/src/commonMain/kotlin/hep/dataforge/values/exoticValues.kt
index d0fb86e8..4b04a036 100644
--- a/dataforge-meta/src/commonMain/kotlin/hep/dataforge/values/exoticValues.kt
+++ b/dataforge-meta/src/commonMain/kotlin/hep/dataforge/values/exoticValues.kt
@@ -4,7 +4,7 @@ package hep.dataforge.values
 /**
  * A value built from string which content and type are parsed on-demand
  */
-class LazyParsedValue(override val string: String) : Value {
+public class LazyParsedValue(override val string: String) : Value {
     private val parsedValue by lazy { string.parseValue() }
 
     override val value: Any? get() = parsedValue.value
@@ -18,12 +18,12 @@ class LazyParsedValue(override val string: String) : Value {
     override fun hashCode(): Int  = string.hashCode()
 }
 
-fun String.lazyParseValue(): LazyParsedValue = LazyParsedValue(this)
+public fun String.lazyParseValue(): LazyParsedValue = LazyParsedValue(this)
 
 /**
  * A performance optimized version of list value for doubles
  */
-class DoubleArrayValue(override val value: DoubleArray) : Value {
+public class DoubleArrayValue(override val value: DoubleArray) : Value {
     override val type: ValueType get() = ValueType.NUMBER
     override val number: Double get() = value.first()
     override val string: String get() = value.first().toString()
@@ -46,4 +46,4 @@ class DoubleArrayValue(override val value: DoubleArray) : Value {
     override fun toString(): String = list.joinToString (prefix = "[", postfix = "]")
 }
 
-fun DoubleArray.asValue(): Value = if(isEmpty()) Null else DoubleArrayValue(this)
+public fun DoubleArray.asValue(): Value = if(isEmpty()) Null else DoubleArrayValue(this)
diff --git a/dataforge-meta/src/commonMain/kotlin/hep/dataforge/values/valueExtensions.kt b/dataforge-meta/src/commonMain/kotlin/hep/dataforge/values/valueExtensions.kt
index 3767e2fb..2171c4ea 100644
--- a/dataforge-meta/src/commonMain/kotlin/hep/dataforge/values/valueExtensions.kt
+++ b/dataforge-meta/src/commonMain/kotlin/hep/dataforge/values/valueExtensions.kt
@@ -1,32 +1,33 @@
 package hep.dataforge.values
 
 import hep.dataforge.meta.Meta
+import hep.dataforge.meta.MetaBuilder
 
 /**
  * Check if value is null
  */
-fun Value.isNull(): Boolean = this == Null
+public fun Value.isNull(): Boolean = this == Null
 
 /**
  * Check if value is list
  */
-fun Value.isList(): Boolean = this.list.size > 1
+public fun Value.isList(): Boolean = this.list.size > 1
 
-val Value.boolean
+public val Value.boolean: Boolean
     get() = this == True
             || this.list.firstOrNull() == True
             || (type == ValueType.STRING && string.toBoolean())
 
 
-val Value.int get() = number.toInt()
-val Value.double get() = number.toDouble()
-val Value.float get() = number.toFloat()
-val Value.short get() = number.toShort()
-val Value.long get() = number.toLong()
+public val Value.int: Int get() = number.toInt()
+public val Value.double: Double get() = number.toDouble()
+public val Value.float: Float get() = number.toFloat()
+public val Value.short: Short get() = number.toShort()
+public val Value.long: Long get() = number.toLong()
 
-val Value.stringList: List<String> get() = list.map { it.string }
+public val Value.stringList: List<String> get() = list.map { it.string }
 
-val Value.doubleArray: DoubleArray
+public val Value.doubleArray: DoubleArray
     get() = if (this is DoubleArrayValue) {
         value
     } else {
@@ -34,4 +35,4 @@ val Value.doubleArray: DoubleArray
     }
 
 
-fun Value.toMeta() = Meta { Meta.VALUE_KEY put this }
\ No newline at end of file
+public fun Value.toMeta(): MetaBuilder = Meta { Meta.VALUE_KEY put this }
\ No newline at end of file
diff --git a/dataforge-meta/src/commonTest/kotlin/hep/dataforge/meta/ConfigTest.kt b/dataforge-meta/src/commonTest/kotlin/hep/dataforge/meta/ConfigTest.kt
new file mode 100644
index 00000000..5e6341aa
--- /dev/null
+++ b/dataforge-meta/src/commonTest/kotlin/hep/dataforge/meta/ConfigTest.kt
@@ -0,0 +1,14 @@
+package hep.dataforge.meta
+
+import kotlin.test.Test
+import kotlin.test.assertEquals
+
+class ConfigTest {
+    @Test
+    fun testIndexedWrite(){
+        val config = Config()
+        config["a[1].b"] = 1
+        assertEquals(null, config["a.b"].int)
+        assertEquals(1, config["a[1].b"].int)
+    }
+}
\ No newline at end of file
diff --git a/dataforge-meta/src/commonTest/kotlin/hep/dataforge/meta/JsonMetaTest.kt b/dataforge-meta/src/commonTest/kotlin/hep/dataforge/meta/JsonMetaTest.kt
index 9086e156..2a1329a7 100644
--- a/dataforge-meta/src/commonTest/kotlin/hep/dataforge/meta/JsonMetaTest.kt
+++ b/dataforge-meta/src/commonTest/kotlin/hep/dataforge/meta/JsonMetaTest.kt
@@ -1,35 +1,33 @@
 package hep.dataforge.meta
 
 import hep.dataforge.meta.descriptors.NodeDescriptor
-import kotlinx.serialization.json.int
-import kotlinx.serialization.json.json
-import kotlinx.serialization.json.jsonArray
+import kotlinx.serialization.json.*
 import kotlin.test.Test
 import kotlin.test.assertEquals
 
 class JsonMetaTest {
-    val json = json {
-        "firstValue" to "a"
-        "secondValue" to "b"
-        "array" to jsonArray {
-            +"1"
-            +"2"
-            +"3"
-        }
-        "nodeArray" to jsonArray {
-            +json {
-                "index" to "1"
-                "value" to 2
-            }
-            +json {
-                "index" to "2"
-                "value" to 3
-            }
-            +json {
-                "index" to "3"
-                "value" to 4
-            }
-        }
+    val json = buildJsonObject {
+        put("firstValue", "a")
+        put("secondValue", "b")
+        put("array", buildJsonArray {
+            add("1")
+            add("2")
+            add("3")
+        })
+        put("nodeArray", buildJsonArray {
+            add(buildJsonObject {
+                put("index", "1")
+                put("value", 2)
+            })
+            add(buildJsonObject {
+                put("index", "2")
+                put("value", 3)
+            })
+            add(buildJsonObject {
+                put("index", "3")
+                put("value", 4)
+            })
+        })
     }
 
     val descriptor = NodeDescriptor{
@@ -45,7 +43,8 @@ class JsonMetaTest {
         //println(meta)
         val reconstructed = meta.toJson(descriptor)
         println(reconstructed)
-        assertEquals(2, reconstructed["nodeArray"]?.jsonArray?.get(1)?.jsonObject?.get("index")?.int)
+        assertEquals(2,
+            reconstructed["nodeArray"]?.jsonArray?.get(1)?.jsonObject?.get("index")?.jsonPrimitive?.int)
         assertEquals(json,reconstructed)
     }
 }
\ No newline at end of file
diff --git a/dataforge-meta/src/commonTest/kotlin/hep/dataforge/meta/MetaDelegateTest.kt b/dataforge-meta/src/commonTest/kotlin/hep/dataforge/meta/MetaDelegateTest.kt
index 925ee36c..6b8442d1 100644
--- a/dataforge-meta/src/commonTest/kotlin/hep/dataforge/meta/MetaDelegateTest.kt
+++ b/dataforge-meta/src/commonTest/kotlin/hep/dataforge/meta/MetaDelegateTest.kt
@@ -1,5 +1,6 @@
 package hep.dataforge.meta
 
+import hep.dataforge.values.asValue
 import kotlin.test.Test
 import kotlin.test.assertEquals
 
@@ -29,7 +30,7 @@ class MetaDelegateTest {
     fun delegateTest() {
 
         val testObject = TestScheme.empty()
-        testObject.config["myValue"] = "theString"
+        testObject.setValue("myValue","theString".asValue())
         testObject.enumValue = TestEnum.NO
 
         testObject.inner = InnerSpec { innerValue = "ddd" }
diff --git a/dataforge-meta/src/commonTest/kotlin/hep/dataforge/meta/SpecificationTest.kt b/dataforge-meta/src/commonTest/kotlin/hep/dataforge/meta/SpecificationTest.kt
index f21c5b2c..587e2049 100644
--- a/dataforge-meta/src/commonTest/kotlin/hep/dataforge/meta/SpecificationTest.kt
+++ b/dataforge-meta/src/commonTest/kotlin/hep/dataforge/meta/SpecificationTest.kt
@@ -1,19 +1,18 @@
 package hep.dataforge.meta
 
-import hep.dataforge.names.Name
 import kotlin.test.Test
 import kotlin.test.assertEquals
 
 class SpecificationTest {
-    class TestStyled(config: Config, defaultProvider: (Name) -> MetaItem<*>?) :
-        Scheme(config, defaultProvider) {
+    class TestStyled : Scheme() {
         var list by numberList(1, 2, 3)
 
         companion object : Specification<TestStyled> {
-            override fun wrap(
-                config: Config,
-                defaultProvider: (Name) -> MetaItem<*>?
-            ): TestStyled = TestStyled(config, defaultProvider)
+            override fun read(meta: Meta, defaultProvider: ItemProvider): TestStyled =
+                TestStyled().apply {
+                    this.config = meta.asConfig()
+
+                }
         }
     }
 
diff --git a/dataforge-meta/src/commonTest/kotlin/hep/dataforge/meta/descriptors/DescriptorTest.kt b/dataforge-meta/src/commonTest/kotlin/hep/dataforge/meta/descriptors/DescriptorTest.kt
index 605cbebd..6d2c3ca5 100644
--- a/dataforge-meta/src/commonTest/kotlin/hep/dataforge/meta/descriptors/DescriptorTest.kt
+++ b/dataforge-meta/src/commonTest/kotlin/hep/dataforge/meta/descriptors/DescriptorTest.kt
@@ -36,7 +36,7 @@ class DescriptorTest {
 
     @Test
     fun testDefaultMetaNode(){
-        val meta = descriptor.buildDefaultMeta()
+        val meta = descriptor.defaultMeta()
         assertEquals(false, meta["aNode.otherNode.otherValue"].boolean)
     }
 }
\ No newline at end of file
diff --git a/dataforge-meta/src/commonTest/kotlin/hep/dataforge/names/NameSerializationTest.kt b/dataforge-meta/src/commonTest/kotlin/hep/dataforge/names/NameSerializationTest.kt
new file mode 100644
index 00000000..7449be2f
--- /dev/null
+++ b/dataforge-meta/src/commonTest/kotlin/hep/dataforge/names/NameSerializationTest.kt
@@ -0,0 +1,18 @@
+package hep.dataforge.names
+
+import kotlinx.serialization.json.Json
+import kotlin.test.Test
+import kotlin.test.assertEquals
+
+
+class NameSerializationTest {
+
+    @Test
+    fun testNameSerialization() {
+        val name = "aaa.bbb.ccc".toName()
+        val json = Json.encodeToJsonElement(Name.serializer(), name)
+        println(json)
+        val reconstructed = Json.decodeFromJsonElement(Name.serializer(), json)
+        assertEquals(name, reconstructed)
+    }
+}
\ No newline at end of file
diff --git a/dataforge-meta/src/jsMain/kotlin/hep/dataforge/meta/DynamicMeta.kt b/dataforge-meta/src/jsMain/kotlin/hep/dataforge/meta/DynamicMeta.kt
index ff23a571..9d76b606 100644
--- a/dataforge-meta/src/jsMain/kotlin/hep/dataforge/meta/DynamicMeta.kt
+++ b/dataforge-meta/src/jsMain/kotlin/hep/dataforge/meta/DynamicMeta.kt
@@ -8,7 +8,7 @@ import hep.dataforge.values.isList
 
 //TODO add Meta wrapper for dynamic
 
-fun Value.toDynamic(): dynamic {
+public fun Value.toDynamic(): dynamic {
     return if (isList()) {
         list.map { it.toDynamic() }.toTypedArray().asDynamic()
     } else {
@@ -19,7 +19,7 @@ fun Value.toDynamic(): dynamic {
 /**
  * Represent or copy this [Meta] to dynamic object to be passed to JS libraries
  */
-fun Meta.toDynamic(): dynamic {
+public fun Meta.toDynamic(): dynamic {
     if (this is DynamicMeta) return this.obj
 
     fun MetaItem<*>.toDynamic(): dynamic = when (this) {
@@ -38,8 +38,8 @@ fun Meta.toDynamic(): dynamic {
     return res
 }
 
-class DynamicMeta(val obj: dynamic) : MetaBase() {
-    private fun keys() = js("Object.keys(this.obj)") as Array<String>
+public class DynamicMeta(internal val obj: dynamic) : MetaBase() {
+    private fun keys(): Array<String> = js("Object").keys(obj)
 
     private fun isArray(@Suppress("UNUSED_PARAMETER") obj: dynamic): Boolean =
         js("Array.isArray(obj)") as Boolean
@@ -47,7 +47,7 @@ class DynamicMeta(val obj: dynamic) : MetaBase() {
     private fun isPrimitive(obj: dynamic): Boolean =
         (jsTypeOf(obj) != "object")
 
-    @Suppress("UNCHECKED_CAST")
+    @Suppress("UNCHECKED_CAST", "USELESS_CAST")
     private fun asItem(obj: dynamic): MetaItem<DynamicMeta>? {
         return when {
             obj == null -> MetaItem.ValueItem(Null)
diff --git a/dataforge-output/api/dataforge-output.api b/dataforge-output/api/dataforge-output.api
new file mode 100644
index 00000000..f991b754
--- /dev/null
+++ b/dataforge-output/api/dataforge-output.api
@@ -0,0 +1,68 @@
+public final class hep/dataforge/output/ConsoleOutputManager : hep/dataforge/context/AbstractPlugin, hep/dataforge/output/OutputManager {
+	public static final field Companion Lhep/dataforge/output/ConsoleOutputManager$Companion;
+	public fun <init> ()V
+	public fun get (Lkotlin/reflect/KClass;Lhep/dataforge/names/Name;Lhep/dataforge/names/Name;Lhep/dataforge/meta/Meta;)Lhep/dataforge/output/Renderer;
+	public fun getTag ()Lhep/dataforge/context/PluginTag;
+}
+
+public final class hep/dataforge/output/ConsoleOutputManager$Companion : hep/dataforge/context/PluginFactory {
+	public fun getTag ()Lhep/dataforge/context/PluginTag;
+	public fun getType ()Lkotlin/reflect/KClass;
+	public fun invoke (Lhep/dataforge/meta/Meta;Lhep/dataforge/context/Context;)Lhep/dataforge/output/ConsoleOutputManager;
+	public synthetic fun invoke (Lhep/dataforge/meta/Meta;Lhep/dataforge/context/Context;)Ljava/lang/Object;
+}
+
+public final class hep/dataforge/output/DefaultTextFormat : hep/dataforge/output/TextFormat {
+	public static final field INSTANCE Lhep/dataforge/output/DefaultTextFormat;
+	public fun getPriority ()I
+	public fun getType ()Lkotlin/reflect/KClass;
+	public fun render (Ljava/lang/Appendable;Ljava/lang/Object;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
+}
+
+public final class hep/dataforge/output/OutputJVMKt {
+	public static final fun getOutput (Lkotlinx/coroutines/Dispatchers;)Lkotlinx/coroutines/CoroutineDispatcher;
+}
+
+public abstract interface class hep/dataforge/output/OutputManager {
+	public abstract fun get (Lkotlin/reflect/KClass;Lhep/dataforge/names/Name;Lhep/dataforge/names/Name;Lhep/dataforge/meta/Meta;)Lhep/dataforge/output/Renderer;
+}
+
+public final class hep/dataforge/output/OutputManager$DefaultImpls {
+	public static synthetic fun get$default (Lhep/dataforge/output/OutputManager;Lkotlin/reflect/KClass;Lhep/dataforge/names/Name;Lhep/dataforge/names/Name;Lhep/dataforge/meta/Meta;ILjava/lang/Object;)Lhep/dataforge/output/Renderer;
+}
+
+public final class hep/dataforge/output/OutputManagerKt {
+	public static final fun getCONSOLE_RENDERER ()Lhep/dataforge/output/Renderer;
+	public static final fun getOutput (Lhep/dataforge/context/Context;)Lhep/dataforge/output/OutputManager;
+	public static final fun render (Lhep/dataforge/output/OutputManager;Ljava/lang/Object;Lhep/dataforge/names/Name;Lhep/dataforge/names/Name;Lhep/dataforge/meta/Meta;)V
+	public static synthetic fun render$default (Lhep/dataforge/output/OutputManager;Ljava/lang/Object;Lhep/dataforge/names/Name;Lhep/dataforge/names/Name;Lhep/dataforge/meta/Meta;ILjava/lang/Object;)V
+}
+
+public abstract interface class hep/dataforge/output/Renderer : hep/dataforge/context/ContextAware {
+	public abstract fun render (Ljava/lang/Object;Lhep/dataforge/meta/Meta;)V
+}
+
+public final class hep/dataforge/output/Renderer$DefaultImpls {
+	public static fun getLogger (Lhep/dataforge/output/Renderer;)Lmu/KLogger;
+	public static synthetic fun render$default (Lhep/dataforge/output/Renderer;Ljava/lang/Object;Lhep/dataforge/meta/Meta;ILjava/lang/Object;)V
+}
+
+public abstract interface class hep/dataforge/output/TextFormat {
+	public static final field Companion Lhep/dataforge/output/TextFormat$Companion;
+	public static final field TEXT_RENDERER_TYPE Ljava/lang/String;
+	public abstract fun getPriority ()I
+	public abstract fun getType ()Lkotlin/reflect/KClass;
+	public abstract fun render (Ljava/lang/Appendable;Ljava/lang/Object;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
+}
+
+public final class hep/dataforge/output/TextFormat$Companion {
+	public static final field TEXT_RENDERER_TYPE Ljava/lang/String;
+}
+
+public final class hep/dataforge/output/TextRenderer : hep/dataforge/output/Renderer {
+	public fun <init> (Lhep/dataforge/context/Context;Ljava/lang/Appendable;)V
+	public fun getContext ()Lhep/dataforge/context/Context;
+	public fun getLogger ()Lmu/KLogger;
+	public fun render (Ljava/lang/Object;Lhep/dataforge/meta/Meta;)V
+}
+
diff --git a/dataforge-output/build.gradle.kts b/dataforge-output/build.gradle.kts
index 6c0a1e53..6051cb1c 100644
--- a/dataforge-output/build.gradle.kts
+++ b/dataforge-output/build.gradle.kts
@@ -1,5 +1,6 @@
 plugins {
-    id("scientifik.mpp")
+    id("ru.mipt.npm.mpp")
+    id("ru.mipt.npm.native")
 }
 
 kotlin {
@@ -7,7 +8,7 @@ kotlin {
         val commonMain by getting{
             dependencies {
                 api(project(":dataforge-context"))
-                api(project(":dataforge-io"))
+                //api(project(":dataforge-io"))
             }
         }
     }
diff --git a/dataforge-output/dataforge-output-html/build.gradle.kts b/dataforge-output/dataforge-output-html/build.gradle.kts
deleted file mode 100644
index 98b9d0bd..00000000
--- a/dataforge-output/dataforge-output-html/build.gradle.kts
+++ /dev/null
@@ -1,26 +0,0 @@
-plugins {
-    id("scientifik.mpp")
-}
-
-val htmlVersion by rootProject.extra("0.6.12")
-
-kotlin {
-    sourceSets {
-        val commonMain by getting {
-            dependencies {
-                api(project(":dataforge-output"))
-                api("org.jetbrains.kotlinx:kotlinx-html-common:$htmlVersion")
-            }
-        }
-        val jsMain by getting {
-            dependencies {
-                api("org.jetbrains.kotlinx:kotlinx-html-js:$htmlVersion")
-            }
-        }
-        val jvmMain by getting{
-            dependencies {
-                api("org.jetbrains.kotlinx:kotlinx-html-jvm:$htmlVersion")
-            }
-        }
-    }
-}
\ No newline at end of file
diff --git a/dataforge-output/dataforge-output-html/src/commonMain/kotlin/hep/dataforge/output/html/HtmlRenderer.kt b/dataforge-output/dataforge-output-html/src/commonMain/kotlin/hep/dataforge/output/html/HtmlRenderer.kt
deleted file mode 100644
index c0aeaaab..00000000
--- a/dataforge-output/dataforge-output-html/src/commonMain/kotlin/hep/dataforge/output/html/HtmlRenderer.kt
+++ /dev/null
@@ -1,79 +0,0 @@
-package hep.dataforge.output.html
-
-import hep.dataforge.context.Context
-import hep.dataforge.meta.Meta
-import hep.dataforge.output.Output
-import hep.dataforge.output.Renderer
-import hep.dataforge.output.TextFormat
-import hep.dataforge.output.html.HtmlBuilder.Companion.HTML_CONVERTER_TYPE
-import hep.dataforge.provider.Type
-import hep.dataforge.provider.top
-import kotlinx.coroutines.Dispatchers
-import kotlinx.coroutines.launch
-import kotlinx.html.TagConsumer
-import kotlinx.html.p
-import kotlin.reflect.KClass
-
-
-class HtmlRenderer<T : Any>(override val context: Context, private val consumer: TagConsumer<*>) : Renderer<T> {
-    private val cache = HashMap<KClass<*>, HtmlBuilder<*>>()
-
-    /**
-     * Find the first [TextFormat] matching the given object type.
-     */
-    override fun render(obj: T, meta: Meta) {
-
-        val builder: HtmlBuilder<*> = if (obj is CharSequence) {
-            DefaultHtmlBuilder
-        } else {
-            val value = cache[obj::class]
-            if (value == null) {
-                val answer =
-                    context.top<HtmlBuilder<*>>(HTML_CONVERTER_TYPE).values.firstOrNull { it.type.isInstance(obj) }
-                if (answer != null) {
-                    cache[obj::class] = answer
-                    answer
-                } else {
-                    DefaultHtmlBuilder
-                }
-            } else {
-                value
-            }
-        }
-        context.launch(Dispatchers.Output) {
-            @Suppress("UNCHECKED_CAST")
-            (builder as HtmlBuilder<T>).run { consumer.render(obj) }
-        }
-    }
-}
-
-/**
- * A text or binary renderer based on [Renderer]
- */
-@Type(HTML_CONVERTER_TYPE)
-interface HtmlBuilder<T : Any> {
-    /**
-     * The priority of this renderer compared to other renderers
-     */
-    val priority: Int
-
-    /**
-     * The type of the content served by this renderer
-     */
-    val type: KClass<T>
-
-    suspend fun TagConsumer<*>.render(obj: T)
-
-    companion object {
-        const val HTML_CONVERTER_TYPE = "dataforge.htmlBuilder"
-    }
-}
-
-object DefaultHtmlBuilder : HtmlBuilder<Any> {
-    override val priority: Int = Int.MAX_VALUE
-    override val type: KClass<Any> = Any::class
-
-    override suspend fun TagConsumer<*>.render(obj: Any) {
-        p { +obj.toString() }
-    }
-}
\ No newline at end of file
diff --git a/dataforge-output/src/commonMain/kotlin/hep/dataforge/output/OutputManager.kt b/dataforge-output/src/commonMain/kotlin/hep/dataforge/output/OutputManager.kt
index a8b1697d..e606c9b7 100644
--- a/dataforge-output/src/commonMain/kotlin/hep/dataforge/output/OutputManager.kt
+++ b/dataforge-output/src/commonMain/kotlin/hep/dataforge/output/OutputManager.kt
@@ -11,7 +11,7 @@ import kotlin.reflect.KClass
 /**
  * A manager for outputs
  */
-interface OutputManager {
+public interface OutputManager {
 
     /**
      * Get an output specialized for given type, name and stage.
@@ -19,7 +19,7 @@ interface OutputManager {
      * @param name represents the name inside the node.
      * @param meta configuration for [Renderer] (not for rendered object)
      */
-    operator fun <T : Any> get(
+    public fun <T : Any> getOutputContainer(
         type: KClass<out T>,
         name: Name,
         stage: Name = Name.EMPTY,
@@ -30,53 +30,46 @@ interface OutputManager {
 /**
  * Get an output manager for a context
  */
-val Context.output: OutputManager get() = plugins.get() ?: ConsoleOutputManager()
+public val Context.output: OutputManager get() = plugins.get() ?: ConsoleOutputManager()
 
 /**
  * Get an output with given [name], [stage] and reified content type
  */
-inline operator fun <reified T : Any> OutputManager.get(
+public inline fun <reified T : Any> OutputManager.getOutputContainer(
     name: Name,
     stage: Name = Name.EMPTY,
     meta: Meta = Meta.EMPTY
 ): Renderer<T> {
-    return get(T::class, name, stage, meta)
+    return getOutputContainer(T::class, name, stage, meta)
 }
 
 /**
  * Directly render an object using the most suitable renderer
  */
-fun OutputManager.render(obj: Any, name: Name, stage: Name = Name.EMPTY, meta: Meta = Meta.EMPTY) =
-    get(obj::class, name, stage).render(obj, meta)
+public fun OutputManager.render(obj: Any, name: Name, stage: Name = Name.EMPTY, meta: Meta = Meta.EMPTY): Unit =
+    getOutputContainer(obj::class, name, stage).render(obj, meta)
 
 /**
  * System console output.
  * The [CONSOLE_RENDERER] is used when no other [OutputManager] is provided.
  */
-val CONSOLE_RENDERER: Renderer<Any> = object : Renderer<Any> {
-    override fun render(obj: Any, meta: Meta) {
-        println(obj)
-    }
+public val CONSOLE_RENDERER: Renderer<Any> = Renderer { obj, meta -> println(obj) }
 
-    override val context: Context get() = Global
-
-}
-
-class ConsoleOutputManager : AbstractPlugin(), OutputManager {
+public class ConsoleOutputManager : AbstractPlugin(), OutputManager {
     override val tag: PluginTag get() = ConsoleOutputManager.tag
 
-    override fun <T : Any> get(type: KClass<out T>, name: Name, stage: Name, meta: Meta): Renderer<T> = CONSOLE_RENDERER
+    override fun <T : Any> getOutputContainer(type: KClass<out T>, name: Name, stage: Name, meta: Meta): Renderer<T> = CONSOLE_RENDERER
 
-    companion object : PluginFactory<ConsoleOutputManager> {
-        override val tag = PluginTag("output.console", group = DATAFORGE_GROUP)
+    public companion object : PluginFactory<ConsoleOutputManager> {
+        override val tag: PluginTag = PluginTag("output.console", group = DATAFORGE_GROUP)
 
-        override val type = ConsoleOutputManager::class
+        override val type: KClass<ConsoleOutputManager> = ConsoleOutputManager::class
 
-        override fun invoke(meta: Meta, context: Context) = ConsoleOutputManager()
+        override fun invoke(meta: Meta, context: Context): ConsoleOutputManager = ConsoleOutputManager()
     }
 }
 
 /**
  * A dispatcher for output tasks.
  */
-expect val Dispatchers.Output: CoroutineDispatcher
\ No newline at end of file
+public expect val Dispatchers.Output: CoroutineDispatcher
\ No newline at end of file
diff --git a/dataforge-output/src/commonMain/kotlin/hep/dataforge/output/Renderer.kt b/dataforge-output/src/commonMain/kotlin/hep/dataforge/output/Renderer.kt
index 9f8009d1..ebcb03ba 100644
--- a/dataforge-output/src/commonMain/kotlin/hep/dataforge/output/Renderer.kt
+++ b/dataforge-output/src/commonMain/kotlin/hep/dataforge/output/Renderer.kt
@@ -10,12 +10,12 @@ import hep.dataforge.meta.Meta
  * based on its configuration and provided meta
  *
  */
-interface Renderer<in T : Any> : ContextAware {
+public fun interface Renderer<in T : Any> {
     /**
      * Render specific object with configuration.
      *
      * By convention actual render is called in asynchronous mode, so this method should never
      * block execution
      */
-    fun render(obj: T, meta: Meta = Meta.EMPTY)
+    public fun render(obj: T, meta: Meta)
 }
diff --git a/dataforge-output/src/commonMain/kotlin/hep/dataforge/output/TextRenderer.kt b/dataforge-output/src/commonMain/kotlin/hep/dataforge/output/TextRenderer.kt
index cc9d24f3..235cdab2 100644
--- a/dataforge-output/src/commonMain/kotlin/hep/dataforge/output/TextRenderer.kt
+++ b/dataforge-output/src/commonMain/kotlin/hep/dataforge/output/TextRenderer.kt
@@ -7,11 +7,47 @@ import hep.dataforge.provider.Type
 import hep.dataforge.provider.top
 import kotlinx.coroutines.Dispatchers
 import kotlinx.coroutines.launch
-import kotlinx.io.Output
-import kotlinx.io.text.writeUtf8String
 import kotlin.reflect.KClass
+import kotlin.reflect.KType
 
-class TextRenderer(override val context: Context, private val output: Output) : Renderer<Any> {
+
+/**
+ * A text or binary renderer based on [Output]
+ */
+@Type(TEXT_RENDERER_TYPE)
+@Deprecated("Bad design")
+public interface TextFormat {
+    /**
+     * The priority of this renderer compared to other renderers
+     */
+    public val priority: Int
+    /**
+     * The type of the content served by this renderer
+     */
+    public val type: KClass<*>
+
+    public suspend fun Appendable.render(obj: Any)
+
+    public companion object {
+        public const val TEXT_RENDERER_TYPE: String = "dataforge.textRenderer"
+    }
+}
+
+@Deprecated("Bad design")
+public object DefaultTextFormat : TextFormat {
+    override val priority: Int = Int.MAX_VALUE
+    override val type: KClass<*> = Any::class
+
+    override suspend fun Appendable.render(obj: Any) {
+        append(obj.toString() + "\n")
+    }
+}
+
+/**
+ * A text-based renderer
+ */
+@Deprecated("Bad design")
+public class TextRenderer(override val context: Context, private val output: Appendable) : Renderer<Any> {
     private val cache = HashMap<KClass<*>, TextFormat>()
 
     /**
@@ -39,34 +75,4 @@ class TextRenderer(override val context: Context, private val output: Output) :
             format.run { output.render(obj) }
         }
     }
-}
-
-/**
- * A text or binary renderer based on [Output]
- */
-@Type(TEXT_RENDERER_TYPE)
-interface TextFormat {
-    /**
-     * The priority of this renderer compared to other renderers
-     */
-    val priority: Int
-    /**
-     * The type of the content served by this renderer
-     */
-    val type: KClass<*>
-
-    suspend fun Output.render(obj: Any)
-
-    companion object {
-        const val TEXT_RENDERER_TYPE = "dataforge.textRenderer"
-    }
-}
-
-object DefaultTextFormat : TextFormat {
-    override val priority: Int = Int.MAX_VALUE
-    override val type: KClass<*> = Any::class
-
-    override suspend fun Output.render(obj: Any) {
-        writeUtf8String(obj.toString() + "\n")
-    }
 }
\ No newline at end of file
diff --git a/dataforge-output/src/jsMain/kotlin/hep/dataforge/output/outputJS.kt b/dataforge-output/src/jsMain/kotlin/hep/dataforge/output/outputJS.kt
index 18a71f07..be973122 100644
--- a/dataforge-output/src/jsMain/kotlin/hep/dataforge/output/outputJS.kt
+++ b/dataforge-output/src/jsMain/kotlin/hep/dataforge/output/outputJS.kt
@@ -4,4 +4,4 @@ import kotlinx.coroutines.CoroutineDispatcher
 import kotlinx.coroutines.Dispatchers
 
 
-actual val Dispatchers.Output: CoroutineDispatcher get() = Dispatchers.Default
\ No newline at end of file
+public actual val Dispatchers.Output: CoroutineDispatcher get() = Default
\ No newline at end of file
diff --git a/dataforge-output/src/jvmMain/kotlin/hep/dataforge/output/outputJVM.kt b/dataforge-output/src/jvmMain/kotlin/hep/dataforge/output/outputJVM.kt
index ea7c416c..24c789fd 100644
--- a/dataforge-output/src/jvmMain/kotlin/hep/dataforge/output/outputJVM.kt
+++ b/dataforge-output/src/jvmMain/kotlin/hep/dataforge/output/outputJVM.kt
@@ -1,5 +1,6 @@
 package hep.dataforge.output
 
+import kotlinx.coroutines.CoroutineDispatcher
 import kotlinx.coroutines.Dispatchers
 
-actual val Dispatchers.Output get() = Dispatchers.IO
\ No newline at end of file
+public actual val Dispatchers.Output: CoroutineDispatcher get() = IO
\ No newline at end of file
diff --git a/dataforge-output/src/nativeMain/kotlin/hep/dataforge/output/outputNative.kt b/dataforge-output/src/nativeMain/kotlin/hep/dataforge/output/outputNative.kt
new file mode 100644
index 00000000..32eb85f5
--- /dev/null
+++ b/dataforge-output/src/nativeMain/kotlin/hep/dataforge/output/outputNative.kt
@@ -0,0 +1,6 @@
+package hep.dataforge.output
+
+import kotlinx.coroutines.CoroutineDispatcher
+import kotlinx.coroutines.Dispatchers
+
+public actual val Dispatchers.Output: CoroutineDispatcher get() = Dispatchers.Default
\ No newline at end of file
diff --git a/dataforge-scripting/api/dataforge-scripting.api b/dataforge-scripting/api/dataforge-scripting.api
new file mode 100644
index 00000000..b41aa156
--- /dev/null
+++ b/dataforge-scripting/api/dataforge-scripting.api
@@ -0,0 +1,6 @@
+public final class hep/dataforge/scripting/Builders {
+	public static final field INSTANCE Lhep/dataforge/scripting/Builders;
+	public final fun buildWorkspace (Ljava/io/File;)Lhep/dataforge/workspace/Workspace;
+	public final fun buildWorkspace (Ljava/lang/String;)Lhep/dataforge/workspace/Workspace;
+}
+
diff --git a/dataforge-scripting/build.gradle.kts b/dataforge-scripting/build.gradle.kts
index c848c1b1..cb16b66e 100644
--- a/dataforge-scripting/build.gradle.kts
+++ b/dataforge-scripting/build.gradle.kts
@@ -1,23 +1,22 @@
 plugins {
-    id("scientifik.mpp")
+    id("ru.mipt.npm.mpp")
 }
 
 kotlin {
-    jvm()
     sourceSets {
-        val commonMain by getting {
+        commonMain {
             dependencies {
                 api(project(":dataforge-workspace"))
                 implementation(kotlin("scripting-common"))
             }
         }
-        val jvmMain by getting {
+        jvmMain{
             dependencies {
-                implementation(kotlin("scripting-jvm-host-embeddable"))
+                implementation(kotlin("scripting-jvm-host"))
                 implementation(kotlin("scripting-jvm"))
             }
         }
-        val jvmTest by getting {
+        jvmTest {
             dependencies {
                 implementation("ch.qos.logback:logback-classic:1.2.3")
             }
diff --git a/dataforge-scripting/src/commonMain/kotlin/hep/dataforge/scripting/Placeholder.kt b/dataforge-scripting/src/commonMain/kotlin/hep/dataforge/scripting/Placeholder.kt
deleted file mode 100644
index a09e35c1..00000000
--- a/dataforge-scripting/src/commonMain/kotlin/hep/dataforge/scripting/Placeholder.kt
+++ /dev/null
@@ -1,4 +0,0 @@
-package hep.dataforge.scripting
-
-internal object Placeholder {
-}
\ No newline at end of file
diff --git a/dataforge-scripting/src/jvmMain/kotlin/hep/dataforge/scripting/Builders.kt b/dataforge-scripting/src/jvmMain/kotlin/hep/dataforge/scripting/Builders.kt
index 2df5a183..e8b1d378 100644
--- a/dataforge-scripting/src/jvmMain/kotlin/hep/dataforge/scripting/Builders.kt
+++ b/dataforge-scripting/src/jvmMain/kotlin/hep/dataforge/scripting/Builders.kt
@@ -13,15 +13,18 @@ import kotlin.script.experimental.jvm.dependenciesFromCurrentContext
 import kotlin.script.experimental.jvm.jvm
 import kotlin.script.experimental.jvmhost.BasicJvmScriptingHost
 
-object Builders {
+public object Builders {
 
-    fun buildWorkspace(source: SourceCode, context: Context = Global): Workspace {
+    private fun buildWorkspace(source: SourceCode, context: Context = Global): Workspace {
         val builder = SimpleWorkspaceBuilder(context)
 
         val workspaceScriptConfiguration = ScriptCompilationConfiguration {
-            baseClass(Any::class)
+//            baseClass(Any::class)
             implicitReceivers(WorkspaceBuilder::class)
-            defaultImports("hep.dataforge.workspace.*")
+            defaultImports(
+                "hep.dataforge.meta.*",
+                "hep.dataforge.workspace.*"
+            )
             jvm {
                 dependenciesFromCurrentContext(wholeClasspath = true)
             }
@@ -49,7 +52,7 @@ object Builders {
         return builder.build()
     }
 
-    fun buildWorkspace(file: File): Workspace = buildWorkspace(file.toScriptSource())
+    public fun buildWorkspace(file: File): Workspace = buildWorkspace(file.toScriptSource())
 
-    fun buildWorkspace(string: String): Workspace = buildWorkspace(string.toScriptSource())
+    public fun buildWorkspace(string: String): Workspace = buildWorkspace(string.toScriptSource())
 }
\ No newline at end of file
diff --git a/dataforge-tables/api/dataforge-tables.api b/dataforge-tables/api/dataforge-tables.api
new file mode 100644
index 00000000..e037773a
--- /dev/null
+++ b/dataforge-tables/api/dataforge-tables.api
@@ -0,0 +1,302 @@
+public final class hep/dataforge/tables/CachedTransformationColumn : hep/dataforge/tables/Column {
+	public fun <init> (Lhep/dataforge/tables/Table;Lkotlin/reflect/KClass;Ljava/lang/String;Lhep/dataforge/meta/Meta;Lkotlin/jvm/functions/Function1;)V
+	public fun get (I)Ljava/lang/Object;
+	public final fun getMapper ()Lkotlin/jvm/functions/Function1;
+	public fun getMeta ()Lhep/dataforge/meta/Meta;
+	public fun getName ()Ljava/lang/String;
+	public fun getSize ()I
+	public final fun getTable ()Lhep/dataforge/tables/Table;
+	public fun getType ()Lkotlin/reflect/KClass;
+}
+
+public final class hep/dataforge/tables/CastColumn : hep/dataforge/tables/Column {
+	public fun <init> (Lhep/dataforge/tables/Column;Lkotlin/reflect/KClass;)V
+	public fun get (I)Ljava/lang/Object;
+	public fun getMeta ()Lhep/dataforge/meta/Meta;
+	public fun getName ()Ljava/lang/String;
+	public final fun getOrigin ()Lhep/dataforge/tables/Column;
+	public fun getSize ()I
+	public fun getType ()Lkotlin/reflect/KClass;
+}
+
+public final class hep/dataforge/tables/CastColumnKt {
+	public static final fun cast (Lhep/dataforge/tables/Column;Lkotlin/reflect/KClass;)Lhep/dataforge/tables/Column;
+	public static final fun get (Ljava/util/Collection;Lhep/dataforge/tables/ColumnHeader;)Lhep/dataforge/tables/Column;
+}
+
+public abstract interface class hep/dataforge/tables/Column : hep/dataforge/tables/ColumnHeader {
+	public abstract fun get (I)Ljava/lang/Object;
+	public abstract fun getSize ()I
+}
+
+public final class hep/dataforge/tables/ColumnDef : hep/dataforge/tables/ColumnHeader {
+	public fun <init> (Ljava/lang/String;Lkotlin/reflect/KClass;Lhep/dataforge/meta/Meta;)V
+	public final fun component1 ()Ljava/lang/String;
+	public final fun component2 ()Lkotlin/reflect/KClass;
+	public final fun component3 ()Lhep/dataforge/meta/Meta;
+	public final fun copy (Ljava/lang/String;Lkotlin/reflect/KClass;Lhep/dataforge/meta/Meta;)Lhep/dataforge/tables/ColumnDef;
+	public static synthetic fun copy$default (Lhep/dataforge/tables/ColumnDef;Ljava/lang/String;Lkotlin/reflect/KClass;Lhep/dataforge/meta/Meta;ILjava/lang/Object;)Lhep/dataforge/tables/ColumnDef;
+	public fun equals (Ljava/lang/Object;)Z
+	public fun getMeta ()Lhep/dataforge/meta/Meta;
+	public fun getName ()Ljava/lang/String;
+	public fun getType ()Lkotlin/reflect/KClass;
+	public fun hashCode ()I
+	public fun toString ()Ljava/lang/String;
+}
+
+public abstract interface class hep/dataforge/tables/ColumnHeader {
+	public abstract fun getMeta ()Lhep/dataforge/meta/Meta;
+	public abstract fun getName ()Ljava/lang/String;
+	public abstract fun getType ()Lkotlin/reflect/KClass;
+}
+
+public final class hep/dataforge/tables/ColumnHeaderKt {
+	public static final fun getTextWidth (Lhep/dataforge/tables/ColumnHeader;)I
+	public static final fun getValueType (Lhep/dataforge/tables/ColumnHeader;)Lhep/dataforge/values/ValueType;
+}
+
+public final class hep/dataforge/tables/ColumnProperty : kotlin/properties/ReadOnlyProperty {
+	public fun <init> (Lhep/dataforge/tables/Table;Lkotlin/reflect/KClass;)V
+	public final fun getTable ()Lhep/dataforge/tables/Table;
+	public final fun getType ()Lkotlin/reflect/KClass;
+	public fun getValue (Ljava/lang/Object;Lkotlin/reflect/KProperty;)Lhep/dataforge/tables/Column;
+	public synthetic fun getValue (Ljava/lang/Object;Lkotlin/reflect/KProperty;)Ljava/lang/Object;
+}
+
+public class hep/dataforge/tables/ColumnScheme : hep/dataforge/meta/Scheme {
+	public static final field Companion Lhep/dataforge/tables/ColumnScheme$Companion;
+	public fun <init> ()V
+	public final fun getTitle ()Ljava/lang/String;
+	public final fun setTitle (Ljava/lang/String;)V
+}
+
+public final class hep/dataforge/tables/ColumnScheme$Companion : hep/dataforge/meta/SchemeSpec {
+}
+
+public final class hep/dataforge/tables/ColumnTable : hep/dataforge/tables/Table {
+	public fun <init> (Ljava/util/Collection;)V
+	public fun getColumns ()Ljava/util/Collection;
+	public fun getHeader ()Ljava/util/List;
+	public fun getRows ()Ljava/util/List;
+	public fun getValue (ILjava/lang/String;)Ljava/lang/Object;
+	public fun rowFlow ()Lkotlinx/coroutines/flow/Flow;
+}
+
+public final class hep/dataforge/tables/IntColumn : hep/dataforge/tables/Column {
+	public static final field Companion Lhep/dataforge/tables/IntColumn$Companion;
+	public fun <init> (Ljava/lang/String;[ILhep/dataforge/meta/Meta;)V
+	public synthetic fun <init> (Ljava/lang/String;[ILhep/dataforge/meta/Meta;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
+	public fun equals (Ljava/lang/Object;)Z
+	public fun get (I)Ljava/lang/Integer;
+	public synthetic fun get (I)Ljava/lang/Object;
+	public final fun getData ()[I
+	public fun getMeta ()Lhep/dataforge/meta/Meta;
+	public fun getName ()Ljava/lang/String;
+	public fun getSize ()I
+	public fun getType ()Lkotlin/reflect/KClass;
+	public fun hashCode ()I
+}
+
+public final class hep/dataforge/tables/IntColumn$Companion {
+}
+
+public final class hep/dataforge/tables/ListColumn : hep/dataforge/tables/Column {
+	public static final field Companion Lhep/dataforge/tables/ListColumn$Companion;
+	public fun <init> (Ljava/lang/String;Ljava/util/List;Lkotlin/reflect/KClass;Lhep/dataforge/meta/Meta;)V
+	public fun get (I)Ljava/lang/Object;
+	public fun getMeta ()Lhep/dataforge/meta/Meta;
+	public fun getName ()Ljava/lang/String;
+	public fun getSize ()I
+	public fun getType ()Lkotlin/reflect/KClass;
+}
+
+public final class hep/dataforge/tables/ListColumn$Companion {
+}
+
+public final class hep/dataforge/tables/MapRow : hep/dataforge/tables/Row {
+	public static final synthetic fun box-impl (Ljava/util/Map;)Lhep/dataforge/tables/MapRow;
+	public static fun constructor-impl (Ljava/util/Map;)Ljava/util/Map;
+	public fun equals (Ljava/lang/Object;)Z
+	public static fun equals-impl (Ljava/util/Map;Ljava/lang/Object;)Z
+	public static final fun equals-impl0 (Ljava/util/Map;Ljava/util/Map;)Z
+	public fun getValue (Ljava/lang/String;)Ljava/lang/Object;
+	public static fun getValue-impl (Ljava/util/Map;Ljava/lang/String;)Ljava/lang/Object;
+	public fun hashCode ()I
+	public static fun hashCode-impl (Ljava/util/Map;)I
+	public fun toString ()Ljava/lang/String;
+	public static fun toString-impl (Ljava/util/Map;)Ljava/lang/String;
+	public final synthetic fun unbox-impl ()Ljava/util/Map;
+}
+
+public final class hep/dataforge/tables/MutableColumnTable : hep/dataforge/tables/Table {
+	public fun <init> (I)V
+	public final fun add (Lhep/dataforge/tables/Column;)V
+	public synthetic fun getColumns ()Ljava/util/Collection;
+	public fun getColumns ()Ljava/util/List;
+	public fun getHeader ()Ljava/util/List;
+	public fun getRows ()Ljava/util/List;
+	public final fun getSize ()I
+	public fun getValue (ILjava/lang/String;)Ljava/lang/Object;
+	public final fun insert (ILhep/dataforge/tables/Column;)V
+	public fun rowFlow ()Lkotlinx/coroutines/flow/Flow;
+}
+
+public final class hep/dataforge/tables/MutableTable : hep/dataforge/tables/RowTable {
+	public fun <init> (Ljava/util/List;Ljava/util/List;)V
+	public final fun column (Ljava/lang/String;Lkotlin/reflect/KClass;Lhep/dataforge/meta/Meta;)Lhep/dataforge/tables/ColumnHeader;
+	public fun getHeader ()Ljava/util/List;
+	public fun getRows ()Ljava/util/List;
+	public final fun row (Ljava/util/Map;)Lhep/dataforge/tables/Row;
+	public final fun row ([Lkotlin/Pair;)Lhep/dataforge/tables/Row;
+}
+
+public final class hep/dataforge/tables/MutableTableKt {
+	public static final fun edit (Lhep/dataforge/tables/Table;Lkotlin/jvm/functions/Function1;)Lhep/dataforge/tables/Table;
+	public static final fun row (Lhep/dataforge/tables/MutableTable;[Lkotlin/Pair;)Lhep/dataforge/tables/Row;
+}
+
+public final class hep/dataforge/tables/RealColumn : hep/dataforge/tables/Column {
+	public static final field Companion Lhep/dataforge/tables/RealColumn$Companion;
+	public fun <init> (Ljava/lang/String;[DLhep/dataforge/meta/Meta;)V
+	public synthetic fun <init> (Ljava/lang/String;[DLhep/dataforge/meta/Meta;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
+	public fun equals (Ljava/lang/Object;)Z
+	public fun get (I)Ljava/lang/Double;
+	public synthetic fun get (I)Ljava/lang/Object;
+	public final fun getData ()[D
+	public fun getMeta ()Lhep/dataforge/meta/Meta;
+	public fun getName ()Ljava/lang/String;
+	public fun getSize ()I
+	public fun getType ()Lkotlin/reflect/KClass;
+	public fun hashCode ()I
+}
+
+public final class hep/dataforge/tables/RealColumn$Companion {
+}
+
+public abstract interface class hep/dataforge/tables/Row {
+	public abstract fun getValue (Ljava/lang/String;)Ljava/lang/Object;
+}
+
+public class hep/dataforge/tables/RowTable : hep/dataforge/tables/Table {
+	public fun <init> (Ljava/util/List;Ljava/util/List;)V
+	public synthetic fun getColumns ()Ljava/util/Collection;
+	public fun getColumns ()Ljava/util/List;
+	public fun getHeader ()Ljava/util/List;
+	public fun getRows ()Ljava/util/List;
+	public fun getValue (ILjava/lang/String;)Ljava/lang/Object;
+	public fun rowFlow ()Lkotlinx/coroutines/flow/Flow;
+}
+
+public final class hep/dataforge/tables/RowTableKt {
+	public static final fun collect (Lhep/dataforge/tables/Rows;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
+}
+
+public abstract interface class hep/dataforge/tables/Rows {
+	public abstract fun getHeader ()Ljava/util/List;
+	public abstract fun rowFlow ()Lkotlinx/coroutines/flow/Flow;
+}
+
+public final class hep/dataforge/tables/SimpleColumnHeader : hep/dataforge/tables/ColumnHeader {
+	public fun <init> (Ljava/lang/String;Lkotlin/reflect/KClass;Lhep/dataforge/meta/Meta;)V
+	public final fun component1 ()Ljava/lang/String;
+	public final fun component2 ()Lkotlin/reflect/KClass;
+	public final fun component3 ()Lhep/dataforge/meta/Meta;
+	public final fun copy (Ljava/lang/String;Lkotlin/reflect/KClass;Lhep/dataforge/meta/Meta;)Lhep/dataforge/tables/SimpleColumnHeader;
+	public static synthetic fun copy$default (Lhep/dataforge/tables/SimpleColumnHeader;Ljava/lang/String;Lkotlin/reflect/KClass;Lhep/dataforge/meta/Meta;ILjava/lang/Object;)Lhep/dataforge/tables/SimpleColumnHeader;
+	public fun equals (Ljava/lang/Object;)Z
+	public fun getMeta ()Lhep/dataforge/meta/Meta;
+	public fun getName ()Ljava/lang/String;
+	public fun getType ()Lkotlin/reflect/KClass;
+	public fun hashCode ()I
+	public fun toString ()Ljava/lang/String;
+}
+
+public abstract interface class hep/dataforge/tables/Table : hep/dataforge/tables/Rows {
+	public static final field Companion Lhep/dataforge/tables/Table$Companion;
+	public abstract fun getColumns ()Ljava/util/Collection;
+	public abstract fun getHeader ()Ljava/util/List;
+	public abstract fun getRows ()Ljava/util/List;
+	public abstract fun getValue (ILjava/lang/String;)Ljava/lang/Object;
+	public abstract fun rowFlow ()Lkotlinx/coroutines/flow/Flow;
+}
+
+public final class hep/dataforge/tables/Table$Companion {
+	public final fun invoke (Lkotlin/jvm/functions/Function1;)Lhep/dataforge/tables/Table;
+}
+
+public final class hep/dataforge/tables/Table$DefaultImpls {
+	public static fun getHeader (Lhep/dataforge/tables/Table;)Ljava/util/List;
+	public static fun rowFlow (Lhep/dataforge/tables/Table;)Lkotlinx/coroutines/flow/Flow;
+}
+
+public final class hep/dataforge/tables/TableKt {
+	public static final fun get (Lhep/dataforge/tables/Row;Lhep/dataforge/tables/ColumnHeader;)Ljava/lang/Object;
+	public static final fun get (Lhep/dataforge/tables/Table;ILhep/dataforge/tables/ColumnHeader;)Ljava/lang/Object;
+	public static final fun get (Ljava/util/Collection;Ljava/lang/String;)Lhep/dataforge/tables/Column;
+	public static final fun getIndices (Lhep/dataforge/tables/Column;)Lkotlin/ranges/IntRange;
+	public static final fun getValue (Lhep/dataforge/tables/Row;Ljava/lang/String;Lkotlin/reflect/KClass;)Ljava/lang/Object;
+	public static final fun getValue (Lhep/dataforge/tables/Table;ILjava/lang/String;Lkotlin/reflect/KClass;)Ljava/lang/Object;
+	public static final fun iterator (Lhep/dataforge/tables/Column;)Ljava/util/Iterator;
+}
+
+public final class hep/dataforge/tables/TransformationColumn : hep/dataforge/tables/Column {
+	public fun <init> (Lhep/dataforge/tables/Table;Lkotlin/reflect/KClass;Ljava/lang/String;Lhep/dataforge/meta/Meta;Lkotlin/jvm/functions/Function1;)V
+	public fun get (I)Ljava/lang/Object;
+	public final fun getMapper ()Lkotlin/jvm/functions/Function1;
+	public fun getMeta ()Lhep/dataforge/meta/Meta;
+	public fun getName ()Ljava/lang/String;
+	public fun getSize ()I
+	public final fun getTable ()Lhep/dataforge/tables/Table;
+	public fun getType ()Lkotlin/reflect/KClass;
+}
+
+public final class hep/dataforge/tables/TransformationColumnKt {
+	public static final fun mapRowsToDouble (Lhep/dataforge/tables/Table;Ljava/lang/String;Lhep/dataforge/meta/Meta;Lkotlin/jvm/functions/Function1;)Lhep/dataforge/tables/RealColumn;
+	public static synthetic fun mapRowsToDouble$default (Lhep/dataforge/tables/Table;Ljava/lang/String;Lhep/dataforge/meta/Meta;Lkotlin/jvm/functions/Function1;ILjava/lang/Object;)Lhep/dataforge/tables/RealColumn;
+	public static final fun mapRowsToInt (Lhep/dataforge/tables/Table;Ljava/lang/String;Lhep/dataforge/meta/Meta;Lkotlin/jvm/functions/Function1;)Lhep/dataforge/tables/IntColumn;
+	public static synthetic fun mapRowsToInt$default (Lhep/dataforge/tables/Table;Ljava/lang/String;Lhep/dataforge/meta/Meta;Lkotlin/jvm/functions/Function1;ILjava/lang/Object;)Lhep/dataforge/tables/IntColumn;
+}
+
+public final class hep/dataforge/tables/ValueColumnScheme : hep/dataforge/tables/ColumnScheme {
+	public fun <init> ()V
+	public final fun getValueType ()Lhep/dataforge/values/ValueType;
+	public final fun setValueType (Lhep/dataforge/values/ValueType;)V
+}
+
+public final class hep/dataforge/tables/io/TextRows : hep/dataforge/tables/Rows {
+	public static final field Companion Lhep/dataforge/tables/io/TextRows$Companion;
+	public fun <init> (Ljava/util/List;Lkotlinx/io/Binary;)V
+	public fun getHeader ()Ljava/util/List;
+	public final fun indexFlow ()Lkotlinx/coroutines/flow/Flow;
+	public fun rowFlow ()Lkotlinx/coroutines/flow/Flow;
+}
+
+public final class hep/dataforge/tables/io/TextRows$Companion {
+}
+
+public final class hep/dataforge/tables/io/TextRowsKt {
+	public static final fun buildRowIndex (Lhep/dataforge/tables/io/TextRows;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
+	public static final fun writeRows (Lkotlinx/io/Output;Lhep/dataforge/tables/Rows;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
+}
+
+public final class hep/dataforge/tables/io/TextTable : hep/dataforge/tables/Table {
+	public static final field Companion Lhep/dataforge/tables/io/TextTable$Companion;
+	public fun <init> (Ljava/util/List;Lkotlinx/io/Binary;Ljava/util/List;)V
+	public fun getColumns ()Ljava/util/Collection;
+	public fun getHeader ()Ljava/util/List;
+	public final fun getIndex ()Ljava/util/List;
+	public fun getRows ()Ljava/util/List;
+	public fun getValue (ILjava/lang/String;)Lhep/dataforge/values/Value;
+	public synthetic fun getValue (ILjava/lang/String;)Ljava/lang/Object;
+	public fun rowFlow ()Lkotlinx/coroutines/flow/Flow;
+}
+
+public final class hep/dataforge/tables/io/TextTable$Companion {
+	public final fun invoke (Ljava/util/List;Lkotlinx/io/Binary;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
+}
+
+public final class hep/dataforge/tables/io/TextTableEnvelopeKt {
+	public static final fun readEnvelope (Lhep/dataforge/tables/io/TextRows$Companion;Lhep/dataforge/io/Envelope;)Lhep/dataforge/tables/io/TextRows;
+	public static final fun wrap (Lhep/dataforge/tables/Table;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
+}
+
diff --git a/dataforge-tables/build.gradle.kts b/dataforge-tables/build.gradle.kts
index 6c0a1e53..e88f70d1 100644
--- a/dataforge-tables/build.gradle.kts
+++ b/dataforge-tables/build.gradle.kts
@@ -1,5 +1,6 @@
 plugins {
-    id("scientifik.mpp")
+    id("ru.mipt.npm.mpp")
+    id("ru.mipt.npm.native")
 }
 
 kotlin {
diff --git a/dataforge-tables/src/commonMain/kotlin/hep/dataforge/tables/ColumnDef.kt b/dataforge-tables/src/commonMain/kotlin/hep/dataforge/tables/ColumnDef.kt
index 2df51d41..2dd2e85b 100644
--- a/dataforge-tables/src/commonMain/kotlin/hep/dataforge/tables/ColumnDef.kt
+++ b/dataforge-tables/src/commonMain/kotlin/hep/dataforge/tables/ColumnDef.kt
@@ -3,7 +3,7 @@ package hep.dataforge.tables
 import hep.dataforge.meta.Meta
 import kotlin.reflect.KClass
 
-data class ColumnDef<out T : Any>(
+public data class ColumnDef<out T : Any>(
     override val name: String,
     override val type: KClass<out T>,
     override val meta: Meta
diff --git a/dataforge-tables/src/commonMain/kotlin/hep/dataforge/tables/ColumnHeader.kt b/dataforge-tables/src/commonMain/kotlin/hep/dataforge/tables/ColumnHeader.kt
index 2023d11b..a226de26 100644
--- a/dataforge-tables/src/commonMain/kotlin/hep/dataforge/tables/ColumnHeader.kt
+++ b/dataforge-tables/src/commonMain/kotlin/hep/dataforge/tables/ColumnHeader.kt
@@ -8,25 +8,25 @@ import hep.dataforge.values.Value
 import hep.dataforge.values.ValueType
 import kotlin.reflect.KClass
 
-typealias TableHeader<C> = List<ColumnHeader<C>>
+public typealias TableHeader<C> = List<ColumnHeader<C>>
 
-typealias ValueTableHeader = List<ColumnHeader<Value>>
+public typealias ValueTableHeader = List<ColumnHeader<Value>>
 
-interface ColumnHeader<out T : Any> {
-    val name: String
-    val type: KClass<out T>
-    val meta: Meta
+public interface ColumnHeader<out T : Any> {
+    public val name: String
+    public val type: KClass<out T>
+    public val meta: Meta
 }
 
-data class SimpleColumnHeader<T : Any>(
+public data class SimpleColumnHeader<T : Any>(
     override val name: String,
     override val type: KClass<out T>,
     override val meta: Meta
 ) : ColumnHeader<T>
 
-val ColumnHeader<Value>.valueType: ValueType? get() = meta["valueType"].string?.let { ValueType.valueOf(it) }
+public val ColumnHeader<Value>.valueType: ValueType? get() = meta["valueType"].string?.let { ValueType.valueOf(it) }
 
-val ColumnHeader<Value>.textWidth: Int
+public val ColumnHeader<Value>.textWidth: Int
     get() = meta["columnWidth"].int ?: when (valueType) {
         ValueType.NUMBER -> 8
         ValueType.STRING -> 16
diff --git a/dataforge-tables/src/commonMain/kotlin/hep/dataforge/tables/ColumnScheme.kt b/dataforge-tables/src/commonMain/kotlin/hep/dataforge/tables/ColumnScheme.kt
index c71ee53f..17968a82 100644
--- a/dataforge-tables/src/commonMain/kotlin/hep/dataforge/tables/ColumnScheme.kt
+++ b/dataforge-tables/src/commonMain/kotlin/hep/dataforge/tables/ColumnScheme.kt
@@ -6,12 +6,12 @@ import hep.dataforge.meta.enum
 import hep.dataforge.meta.string
 import hep.dataforge.values.ValueType
 
-open class ColumnScheme : Scheme() {
-    var title by string()
+public open class ColumnScheme : Scheme() {
+    public var title: String? by string()
 
-    companion object : SchemeSpec<ColumnScheme>(::ColumnScheme)
+    public companion object : SchemeSpec<ColumnScheme>(::ColumnScheme)
 }
 
-class ValueColumnScheme : ColumnScheme() {
-    var valueType by enum(ValueType.STRING)
+public class ValueColumnScheme : ColumnScheme() {
+    public var valueType: ValueType by enum(ValueType.STRING)
 }
\ No newline at end of file
diff --git a/dataforge-tables/src/commonMain/kotlin/hep/dataforge/tables/ColumnTable.kt b/dataforge-tables/src/commonMain/kotlin/hep/dataforge/tables/ColumnTable.kt
index db80b6fa..e79ebd08 100644
--- a/dataforge-tables/src/commonMain/kotlin/hep/dataforge/tables/ColumnTable.kt
+++ b/dataforge-tables/src/commonMain/kotlin/hep/dataforge/tables/ColumnTable.kt
@@ -3,7 +3,7 @@ package hep.dataforge.tables
 /**
  * @param T bottom type for all columns in the table
  */
-class ColumnTable<T : Any>(override val columns: Collection<Column<T>>) : Table<T> {
+public class ColumnTable<T : Any>(override val columns: Collection<Column<T>>) : Table<T> {
     private val rowsNum = columns.first().size
 
     init {
diff --git a/dataforge-tables/src/commonMain/kotlin/hep/dataforge/tables/ListColumn.kt b/dataforge-tables/src/commonMain/kotlin/hep/dataforge/tables/ListColumn.kt
index fc7f03ea..7b0549fa 100644
--- a/dataforge-tables/src/commonMain/kotlin/hep/dataforge/tables/ListColumn.kt
+++ b/dataforge-tables/src/commonMain/kotlin/hep/dataforge/tables/ListColumn.kt
@@ -3,7 +3,7 @@ package hep.dataforge.tables
 import hep.dataforge.meta.Meta
 import kotlin.reflect.KClass
 
-class ListColumn<T : Any>(
+public class ListColumn<T : Any>(
     override val name: String,
     private val data: List<T?>,
     override val type: KClass<out T>,
@@ -13,14 +13,14 @@ class ListColumn<T : Any>(
 
     override fun get(index: Int): T? = data[index]
 
-    companion object {
-        inline operator fun <reified T : Any> invoke(
+    public companion object {
+        public inline operator fun <reified T : Any> invoke(
             name: String,
             def: ColumnScheme,
             data: List<T?>
         ): ListColumn<T> = ListColumn(name, data, T::class, def.toMeta())
 
-        inline operator fun <reified T : Any> invoke(
+        public inline operator fun <reified T : Any> invoke(
             name: String,
             def: ColumnScheme,
             size: Int,
@@ -29,7 +29,7 @@ class ListColumn<T : Any>(
     }
 }
 
-inline fun <T : Any, reified R : Any> Column<T>.map(meta: Meta = this.meta, noinline block: (T?) -> R): Column<R> {
+public inline fun <T : Any, reified R : Any> Column<T>.map(meta: Meta = this.meta, noinline block: (T?) -> R): Column<R> {
     val data = List(size) { block(get(it)) }
     return ListColumn(name, data, R::class, meta)
 }
\ No newline at end of file
diff --git a/dataforge-tables/src/commonMain/kotlin/hep/dataforge/tables/MutableColumnTable.kt b/dataforge-tables/src/commonMain/kotlin/hep/dataforge/tables/MutableColumnTable.kt
index 4b93a13d..eb69d7e7 100644
--- a/dataforge-tables/src/commonMain/kotlin/hep/dataforge/tables/MutableColumnTable.kt
+++ b/dataforge-tables/src/commonMain/kotlin/hep/dataforge/tables/MutableColumnTable.kt
@@ -3,7 +3,7 @@ package hep.dataforge.tables
 /**
  * Mutable table with a fixed size, but dynamic columns
  */
-class MutableColumnTable<C: Any>(val size: Int) : Table<C> {
+public class MutableColumnTable<C: Any>(public val size: Int) : Table<C> {
     private val _columns = ArrayList<Column<C>>()
 
     override val columns: List<Column<C>> get() = _columns
@@ -16,7 +16,7 @@ class MutableColumnTable<C: Any>(val size: Int) : Table<C> {
     /**
      * Add a fixed column to the end of the table
      */
-    fun add(column: Column<C>) {
+    public fun add(column: Column<C>) {
         require(column.size == this.size) { "Required column size $size, but found ${column.size}" }
         _columns.add(column)
     }
@@ -24,7 +24,7 @@ class MutableColumnTable<C: Any>(val size: Int) : Table<C> {
     /**
      * Insert a column at [index]
      */
-    fun insert(index: Int, column: Column<C>) {
+    public fun insert(index: Int, column: Column<C>) {
         require(column.size == this.size) { "Required column size $size, but found ${column.size}" }
         _columns.add(index, column)
     }
diff --git a/dataforge-tables/src/commonMain/kotlin/hep/dataforge/tables/MutableTable.kt b/dataforge-tables/src/commonMain/kotlin/hep/dataforge/tables/MutableTable.kt
index a59108a6..f4070146 100644
--- a/dataforge-tables/src/commonMain/kotlin/hep/dataforge/tables/MutableTable.kt
+++ b/dataforge-tables/src/commonMain/kotlin/hep/dataforge/tables/MutableTable.kt
@@ -1,40 +1,41 @@
 package hep.dataforge.tables
 
 import hep.dataforge.meta.Meta
+import hep.dataforge.meta.invoke
 import hep.dataforge.values.Value
 import kotlin.reflect.KClass
 
-class MutableTable<C : Any>(
+public class MutableTable<C : Any>(
     override val rows: MutableList<Row<C>>,
     override val header: MutableList<ColumnHeader<C>>
 ) : RowTable<C>(rows, header) {
 
-    fun <R : C> column(name: String, type: KClass<out R>, meta: Meta): ColumnHeader<R> {
+    public fun <R : C> column(name: String, type: KClass<out R>, meta: Meta): ColumnHeader<R> {
         val column = SimpleColumnHeader(name, type, meta)
         header.add(column)
         return column
     }
 
-    inline fun <reified T : C> column(
+    public inline fun <reified T : C> column(
         name: String,
         noinline columnMetaBuilder: ColumnScheme.() -> Unit = {}
     ): ColumnHeader<T> {
         return column(name, T::class, ColumnScheme(columnMetaBuilder).toMeta())
     }
 
-    fun row(map: Map<String, C?>): Row<C> {
+    public fun row(map: Map<String, C?>): Row<C> {
         val row = MapRow(map)
         rows.add(row)
         return row
     }
 
-    fun <T : C> row(vararg pairs: Pair<ColumnHeader<T>, T>): Row<C> =
+    public fun <T : C> row(vararg pairs: Pair<ColumnHeader<T>, T>): Row<C> =
         row(pairs.associate { it.first.name to it.second })
 }
 
-fun MutableTable<Value>.row(vararg pairs: Pair<ColumnHeader<Value>, Any?>): Row<Value> =
+public fun MutableTable<Value>.row(vararg pairs: Pair<ColumnHeader<Value>, Any?>): Row<Value> =
     row(pairs.associate { it.first.name to Value.of(it.second) })
 
-fun <C : Any> Table<C>.edit(block: MutableTable<C>.() -> Unit): Table<C> {
+public fun <C : Any> Table<C>.edit(block: MutableTable<C>.() -> Unit): Table<C> {
     return MutableTable(rows.toMutableList(), header.toMutableList()).apply(block)
 }
\ No newline at end of file
diff --git a/dataforge-tables/src/commonMain/kotlin/hep/dataforge/tables/RowTable.kt b/dataforge-tables/src/commonMain/kotlin/hep/dataforge/tables/RowTable.kt
index aa3449fb..9ea908cc 100644
--- a/dataforge-tables/src/commonMain/kotlin/hep/dataforge/tables/RowTable.kt
+++ b/dataforge-tables/src/commonMain/kotlin/hep/dataforge/tables/RowTable.kt
@@ -4,7 +4,7 @@ import hep.dataforge.meta.Meta
 import kotlinx.coroutines.flow.toList
 import kotlin.reflect.KClass
 
-inline class MapRow<C : Any>(val values: Map<String, C?>) : Row<C> {
+public inline class MapRow<C : Any>(private val values: Map<String, C?>) : Row<C> {
     override fun getValue(column: String): C? = values[column]
 }
 
@@ -17,10 +17,10 @@ internal class RowTableColumn<C : Any, T : C>(val table: Table<C>, val header: C
     override fun get(index: Int): T? = table.rows[index].getValue(name, type)
 }
 
-open class RowTable<C : Any>(override val rows: List<Row<C>>, override val header: List<ColumnHeader<C>>) : Table<C> {
+public open class RowTable<C : Any>(override val rows: List<Row<C>>, override val header: List<ColumnHeader<C>>) : Table<C> {
     override fun getValue(row: Int, column: String): C? = rows[row].getValue(column)
 
     override val columns: List<Column<C>> get() = header.map { RowTableColumn(this, it) }
 }
 
-suspend fun <C : Any> Rows<C>.collect(): Table<C> = this as? Table<C> ?: RowTable(rowFlow().toList(), header)
\ No newline at end of file
+public suspend fun <C : Any> Rows<C>.collect(): Table<C> = this as? Table<C> ?: RowTable(rowFlow().toList(), header)
\ No newline at end of file
diff --git a/dataforge-tables/src/commonMain/kotlin/hep/dataforge/tables/Table.kt b/dataforge-tables/src/commonMain/kotlin/hep/dataforge/tables/Table.kt
index 0197955d..72875a05 100644
--- a/dataforge-tables/src/commonMain/kotlin/hep/dataforge/tables/Table.kt
+++ b/dataforge-tables/src/commonMain/kotlin/hep/dataforge/tables/Table.kt
@@ -9,57 +9,57 @@ import kotlin.reflect.cast
  * Finite or infinite row set. Rows are produced in a lazy suspendable [Flow].
  * Each row must contain at least all the fields mentioned in [header].
  */
-interface Rows<out T : Any> {
-    val header: TableHeader<T>
-    fun rowFlow(): Flow<Row<T>>
+public interface Rows<out T : Any> {
+    public val header: TableHeader<T>
+    public fun rowFlow(): Flow<Row<T>>
 }
 
-interface Table<out T : Any> : Rows<T> {
-    fun getValue(row: Int, column: String): T?
-    val columns: Collection<Column<T>>
+public interface Table<out T : Any> : Rows<T> {
+    public fun getValue(row: Int, column: String): T?
+    public val columns: Collection<Column<T>>
     override val header: TableHeader<T> get() = columns.toList()
-    val rows: List<Row<T>>
+    public val rows: List<Row<T>>
     override fun rowFlow(): Flow<Row<T>> = rows.asFlow()
 
     /**
      * Apply typed query to this table and return lazy [Flow] of resulting rows. The flow could be empty.
      */
     //fun select(query: Any): Flow<Row> = error("Query of type ${query::class} is not supported by this table")
-    companion object {
-        inline operator fun <T : Any> invoke(block: MutableTable<T>.() -> Unit): Table<T> =
+    public companion object {
+        public inline operator fun <T : Any> invoke(block: MutableTable<T>.() -> Unit): Table<T> =
             MutableTable<T>(arrayListOf(), arrayListOf()).apply(block)
     }
 }
 
-fun <C : Any, T : C> Table<C>.getValue(row: Int, column: String, type: KClass<out T>): T? =
+public fun <C : Any, T : C> Table<C>.getValue(row: Int, column: String, type: KClass<out T>): T? =
     type.cast(getValue(row, column))
 
-operator fun <T : Any> Collection<Column<T>>.get(name: String): Column<T>? = find { it.name == name }
+public operator fun <T : Any> Collection<Column<T>>.get(name: String): Column<T>? = find { it.name == name }
 
-inline operator fun <C : Any, reified T : C> Table<C>.get(row: Int, column: String): T? =
+public inline operator fun <C : Any, reified T : C> Table<C>.get(row: Int, column: String): T? =
     getValue(row, column, T::class)
 
-operator fun <C : Any, T : C> Table<C>.get(row: Int, column: ColumnHeader<T>): T? =
+public operator fun <C : Any, T : C> Table<C>.get(row: Int, column: ColumnHeader<T>): T? =
     getValue(row, column.name, column.type)
 
-interface Column<out T : Any> : ColumnHeader<T> {
-    val size: Int
-    operator fun get(index: Int): T?
+public interface Column<out T : Any> : ColumnHeader<T> {
+    public val size: Int
+    public operator fun get(index: Int): T?
 }
 
-val Column<*>.indices get() = (0 until size)
+public val Column<*>.indices: IntRange get() = (0 until size)
 
-operator fun <T : Any> Column<T>.iterator() = iterator {
+public operator fun <T : Any> Column<T>.iterator(): Iterator<T?> = iterator {
     for (i in indices) {
         yield(get(i))
     }
 }
 
-interface Row<out T : Any> {
-    fun getValue(column: String): T?
+public interface Row<out T : Any> {
+    public fun getValue(column: String): T?
 }
 
-fun <C : Any, T : C> Row<C>.getValue(column: String, type: KClass<out T>): T? = type.cast(getValue(column))
+public fun <C : Any, T : C> Row<C>.getValue(column: String, type: KClass<out T>): T? = type.cast(getValue(column))
 
-inline operator fun <reified T : Any> Row<T>.get(column: String): T? = T::class.cast(getValue(column))
-operator fun <C : Any, T : C> Row<C>.get(column: ColumnHeader<T>): T? = getValue(column.name, column.type)
\ No newline at end of file
+public inline operator fun <reified T : Any> Row<T>.get(column: String): T? = T::class.cast(getValue(column))
+public operator fun <C : Any, T : C> Row<C>.get(column: ColumnHeader<T>): T? = getValue(column.name, column.type)
\ No newline at end of file
diff --git a/dataforge-tables/src/commonMain/kotlin/hep/dataforge/tables/TransformationColumn.kt b/dataforge-tables/src/commonMain/kotlin/hep/dataforge/tables/TransformationColumn.kt
index 3c4fa2b4..83fdc06b 100644
--- a/dataforge-tables/src/commonMain/kotlin/hep/dataforge/tables/TransformationColumn.kt
+++ b/dataforge-tables/src/commonMain/kotlin/hep/dataforge/tables/TransformationColumn.kt
@@ -6,12 +6,12 @@ import kotlin.reflect.KClass
 /**
  * A virtual column obtained by transforming Given row to a single value
  */
-class TransformationColumn<T : Any, R : Any>(
-    val table: Table<T>,
+public class TransformationColumn<T : Any, R : Any>(
+    public val table: Table<T>,
     override val type: KClass<out R>,
     override val name: String,
     override val meta: Meta,
-    val mapper: (Row<T>) -> R?
+    public val mapper: (Row<T>) -> R?
 ) : Column<R> {
     override val size: Int get() = table.rows.size
 
@@ -23,12 +23,12 @@ class TransformationColumn<T : Any, R : Any>(
  *
  * Calls are not thread safe
  */
-class CachedTransformationColumn<T : Any, R : Any>(
-    val table: Table<T>,
+public class CachedTransformationColumn<T : Any, R : Any>(
+    public val table: Table<T>,
     override val type: KClass<out R>,
     override val name: String,
     override val meta: Meta,
-    val mapper: (Row<T>) -> R?
+    public val mapper: (Row<T>) -> R?
 ) : Column<R> {
     override val size: Int get() = table.rows.size
     private val values: HashMap<Int, R?> = HashMap()
@@ -38,7 +38,7 @@ class CachedTransformationColumn<T : Any, R : Any>(
 /**
  * Create a virtual column from a given column
  */
-inline fun <T : Any, reified R : Any> Table<T>.mapRows(
+public inline fun <T : Any, reified R : Any> Table<T>.mapRows(
     name: String,
     meta: Meta = Meta.EMPTY,
     cache: Boolean = false,
@@ -49,12 +49,12 @@ inline fun <T : Any, reified R : Any> Table<T>.mapRows(
     TransformationColumn(this, R::class, name, meta, mapper)
 }
 
-fun <T : Any> Table<T>.mapRowsToDouble(name: String, meta: Meta = Meta.EMPTY, block: (Row<T>) -> Double): RealColumn {
+public fun <T : Any> Table<T>.mapRowsToDouble(name: String, meta: Meta = Meta.EMPTY, block: (Row<T>) -> Double): RealColumn {
     val data = DoubleArray(rows.size) { block(rows[it]) }
     return RealColumn(name, data, meta)
 }
 
-fun <T : Any> Table<T>.mapRowsToInt(name: String, meta: Meta = Meta.EMPTY, block: (Row<T>) -> Int): IntColumn {
+public fun <T : Any> Table<T>.mapRowsToInt(name: String, meta: Meta = Meta.EMPTY, block: (Row<T>) -> Int): IntColumn {
     val data = IntArray(rows.size) { block(rows[it]) }
     return IntColumn(name, data, meta)
 }
\ No newline at end of file
diff --git a/dataforge-tables/src/commonMain/kotlin/hep/dataforge/tables/io/TextRows.kt b/dataforge-tables/src/commonMain/kotlin/hep/dataforge/tables/io/TextRows.kt
index 293031f8..31f5baaa 100644
--- a/dataforge-tables/src/commonMain/kotlin/hep/dataforge/tables/io/TextRows.kt
+++ b/dataforge-tables/src/commonMain/kotlin/hep/dataforge/tables/io/TextRows.kt
@@ -32,12 +32,12 @@ private fun readLine(header: ValueTableHeader, line: String): Row<Value> {
  * Finite or infinite [Rows] created from a fixed width text binary
  */
 @ExperimentalIoApi
-class TextRows(override val header: ValueTableHeader, val binary: Binary) : Rows<Value> {
+public class TextRows(override val header: ValueTableHeader, private val binary: Binary) : Rows<Value> {
 
     /**
      * A flow of indexes of string start offsets ignoring empty strings
      */
-    fun indexFlow(): Flow<Int> = binary.read {
+    public fun indexFlow(): Flow<Int> = binary.read {
         var counter: Int = 0
         flow {
             val string = readUtf8StringUntilDelimiter('\n')
@@ -59,23 +59,23 @@ class TextRows(override val header: ValueTableHeader, val binary: Binary) : Rows
         }
     }
 
-    companion object
+    public companion object
 }
 
 /**
  * Create a row offset index for [TextRows]
  */
 @ExperimentalIoApi
-suspend fun TextRows.buildRowIndex(): List<Int> = indexFlow().toList()
+public suspend fun TextRows.buildRowIndex(): List<Int> = indexFlow().toList()
 
 /**
  * Finite table created from [RandomAccessBinary] with fixed width text table
  */
 @ExperimentalIoApi
-class TextTable(
+public class TextTable(
     override val header: ValueTableHeader,
-    val binary: Binary,
-    val index: List<Int>
+    private val binary: Binary,
+    public val index: List<Int>
 ) : Table<Value> {
 
     override val columns: Collection<Column<Value>> get() = header.map { RowTableColumn(this, it) }
@@ -96,8 +96,8 @@ class TextTable(
         return readAt(offset)[column]
     }
 
-    companion object {
-        suspend operator fun invoke(header: ValueTableHeader, binary: Binary): TextTable {
+    public companion object {
+        public suspend operator fun invoke(header: ValueTableHeader, binary: Binary): TextTable {
             val index = TextRows(header, binary).buildRowIndex()
             return TextTable(header, binary, index)
         }
@@ -131,7 +131,7 @@ private fun Output.writeValue(value: Value, width: Int, left: Boolean = true) {
 /**
  * Write rows without header to the output
  */
-suspend fun Output.writeRows(rows: Rows<Value>) {
+public suspend fun Output.writeRows(rows: Rows<Value>) {
     val widths: List<Int> = rows.header.map {
         it.textWidth
     }
diff --git a/dataforge-tables/src/commonMain/kotlin/hep/dataforge/tables/io/textTableEnvelope.kt b/dataforge-tables/src/commonMain/kotlin/hep/dataforge/tables/io/textTableEnvelope.kt
index e634346c..4deb84e6 100644
--- a/dataforge-tables/src/commonMain/kotlin/hep/dataforge/tables/io/textTableEnvelope.kt
+++ b/dataforge-tables/src/commonMain/kotlin/hep/dataforge/tables/io/textTableEnvelope.kt
@@ -12,7 +12,7 @@ import kotlinx.io.asBinary
 
 
 @ExperimentalIoApi
-suspend fun Table<Value>.wrap(): Envelope = Envelope {
+public suspend fun Table<Value>.wrap(): Envelope = Envelope {
     meta {
         header.forEachIndexed { index, columnHeader ->
             set("column", index.toString(), Meta {
@@ -32,9 +32,9 @@ suspend fun Table<Value>.wrap(): Envelope = Envelope {
 
 @DFExperimental
 @ExperimentalIoApi
-fun TextRows.Companion.readEnvelope(envelope: Envelope): TextRows {
+public fun TextRows.Companion.readEnvelope(envelope: Envelope): TextRows {
     val header = envelope.meta.getIndexed("column")
-        .entries.sortedBy { it.key.toInt() }
+        .entries.sortedBy { it.key?.toInt() }
         .map { (_, item) ->
             SimpleColumnHeader(item.node["name"].string!!, Value::class, item.node["meta"].node ?: Meta.EMPTY)
         }
diff --git a/dataforge-tables/src/commonMain/kotlin/hep/dataforge/tables/numericColumns.kt b/dataforge-tables/src/commonMain/kotlin/hep/dataforge/tables/numericColumns.kt
index 7f80b082..86868a22 100644
--- a/dataforge-tables/src/commonMain/kotlin/hep/dataforge/tables/numericColumns.kt
+++ b/dataforge-tables/src/commonMain/kotlin/hep/dataforge/tables/numericColumns.kt
@@ -1,12 +1,13 @@
 package hep.dataforge.tables
 
 import hep.dataforge.meta.Meta
+import hep.dataforge.meta.invoke
 import kotlin.reflect.KClass
 
 
-class RealColumn(
+public class RealColumn(
     override val name: String,
-    val data: DoubleArray,
+    public val data: DoubleArray,
     override val meta: Meta = Meta.EMPTY
 ) : Column<Double> {
     override val type: KClass<out Double> get() = Double::class
@@ -34,8 +35,8 @@ class RealColumn(
         return result
     }
 
-    companion object {
-        inline operator fun <reified T : Any> invoke(
+    public companion object {
+        public inline operator fun <reified T : Any> invoke(
             name: String,
             data: DoubleArray,
             noinline metaBuilder: ColumnScheme.() -> Unit
@@ -43,9 +44,9 @@ class RealColumn(
     }
 }
 
-class IntColumn(
+public class IntColumn(
     override val name: String,
-    val data: IntArray,
+    public val data: IntArray,
     override val meta: Meta = Meta.EMPTY
 ) : Column<Int> {
     override val type: KClass<out Int> get() = Int::class
@@ -73,8 +74,8 @@ class IntColumn(
         return result
     }
 
-    companion object {
-        inline operator fun <reified T : Any> invoke(
+    public companion object {
+        public inline operator fun <reified T : Any> invoke(
             name: String,
             data: IntArray,
             noinline metaBuilder: ColumnScheme.() -> Unit
diff --git a/dataforge-workspace/api/dataforge-workspace.api b/dataforge-workspace/api/dataforge-workspace.api
new file mode 100644
index 00000000..c410f094
--- /dev/null
+++ b/dataforge-workspace/api/dataforge-workspace.api
@@ -0,0 +1,273 @@
+public final class hep/dataforge/workspace/AllDataDependency : hep/dataforge/workspace/Dependency {
+	public fun <init> ()V
+	public fun <init> (Lhep/dataforge/names/Name;)V
+	public synthetic fun <init> (Lhep/dataforge/names/Name;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
+	public fun apply (Lhep/dataforge/workspace/Workspace;)Lhep/dataforge/data/DataNode;
+	public synthetic fun toMeta ()Lhep/dataforge/meta/Meta;
+	public fun toMeta ()Lhep/dataforge/meta/MetaBuilder;
+}
+
+public final class hep/dataforge/workspace/DataDependency : hep/dataforge/workspace/Dependency {
+	public fun <init> (Lhep/dataforge/data/DataFilter;Lhep/dataforge/names/Name;)V
+	public synthetic fun <init> (Lhep/dataforge/data/DataFilter;Lhep/dataforge/names/Name;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
+	public fun apply (Lhep/dataforge/workspace/Workspace;)Lhep/dataforge/data/DataNode;
+	public fun toMeta ()Lhep/dataforge/meta/Meta;
+}
+
+public abstract class hep/dataforge/workspace/Dependency : hep/dataforge/meta/MetaRepr {
+	public abstract fun apply (Lhep/dataforge/workspace/Workspace;)Lhep/dataforge/data/DataNode;
+}
+
+public final class hep/dataforge/workspace/DirectTaskDependency : hep/dataforge/workspace/TaskDependency {
+	public static final field Companion Lhep/dataforge/workspace/DirectTaskDependency$Companion;
+	public fun <init> (Lhep/dataforge/workspace/Task;Lhep/dataforge/meta/Meta;Lhep/dataforge/names/Name;)V
+	public fun getName ()Lhep/dataforge/names/Name;
+	public final fun getTask ()Lhep/dataforge/workspace/Task;
+	public fun resolveTask (Lhep/dataforge/workspace/Workspace;)Lhep/dataforge/workspace/Task;
+}
+
+public final class hep/dataforge/workspace/DirectTaskDependency$Companion {
+	public final fun getDIRECT_TASK_NAME ()Lhep/dataforge/names/Name;
+}
+
+public final class hep/dataforge/workspace/EnvelopeDataKt {
+	public static final fun toData (Lhep/dataforge/io/Envelope;Lkotlin/reflect/KClass;Lhep/dataforge/io/IOFormat;)Lhep/dataforge/data/Data;
+	public static final fun toEnvelope (Lhep/dataforge/data/Data;Lhep/dataforge/io/IOFormat;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
+}
+
+public final class hep/dataforge/workspace/FileDataKt {
+	public static final fun file (Lhep/dataforge/data/DataTreeBuilder;Lhep/dataforge/io/IOPlugin;Ljava/nio/file/Path;Lkotlin/jvm/functions/Function2;)V
+	public static final fun readDataDirectory (Lhep/dataforge/io/IOPlugin;Ljava/nio/file/Path;Lkotlin/reflect/KClass;Lkotlin/jvm/functions/Function2;)Lhep/dataforge/data/DataNode;
+	public static final fun readDataFile (Lhep/dataforge/io/IOPlugin;Ljava/nio/file/Path;Lkotlin/reflect/KClass;Lkotlin/jvm/functions/Function2;)Lhep/dataforge/data/Data;
+	public static final fun writeDataDirectory (Lhep/dataforge/io/IOPlugin;Ljava/nio/file/Path;Lhep/dataforge/data/DataNode;Lhep/dataforge/io/IOFormat;Lhep/dataforge/io/EnvelopeFormat;Lhep/dataforge/io/MetaFormatFactory;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
+	public static synthetic fun writeDataDirectory$default (Lhep/dataforge/io/IOPlugin;Ljava/nio/file/Path;Lhep/dataforge/data/DataNode;Lhep/dataforge/io/IOFormat;Lhep/dataforge/io/EnvelopeFormat;Lhep/dataforge/io/MetaFormatFactory;Lkotlin/coroutines/Continuation;ILjava/lang/Object;)Ljava/lang/Object;
+	public static final fun writeZip (Lhep/dataforge/io/IOPlugin;Ljava/nio/file/Path;Lhep/dataforge/data/DataNode;Lhep/dataforge/io/IOFormat;Lhep/dataforge/io/EnvelopeFormat;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
+	public static synthetic fun writeZip$default (Lhep/dataforge/io/IOPlugin;Ljava/nio/file/Path;Lhep/dataforge/data/DataNode;Lhep/dataforge/io/IOFormat;Lhep/dataforge/io/EnvelopeFormat;Lkotlin/coroutines/Continuation;ILjava/lang/Object;)Ljava/lang/Object;
+}
+
+public final class hep/dataforge/workspace/GenericTask : hep/dataforge/workspace/Task {
+	public fun <init> (Lhep/dataforge/names/Name;Lkotlin/reflect/KClass;Lhep/dataforge/meta/descriptors/NodeDescriptor;Lkotlin/jvm/functions/Function2;Lkotlin/jvm/functions/Function1;)V
+	public fun build (Lhep/dataforge/workspace/Workspace;Lhep/dataforge/meta/Meta;)Lhep/dataforge/workspace/TaskModel;
+	public synthetic fun getDescriptor ()Lhep/dataforge/meta/descriptors/ItemDescriptor;
+	public fun getDescriptor ()Lhep/dataforge/meta/descriptors/NodeDescriptor;
+	public fun getName ()Lhep/dataforge/names/Name;
+	public fun getType ()Lkotlin/reflect/KClass;
+	public fun isTerminal ()Z
+	public fun run (Lhep/dataforge/workspace/Workspace;Lhep/dataforge/workspace/TaskModel;)Lhep/dataforge/data/DataNode;
+	public fun validate (Lhep/dataforge/workspace/TaskModel;)V
+}
+
+public final class hep/dataforge/workspace/SimpleWorkspace : hep/dataforge/workspace/Workspace {
+	public static final field Companion Lhep/dataforge/workspace/SimpleWorkspace$Companion;
+	public fun <init> (Lhep/dataforge/context/Context;Lhep/dataforge/data/DataNode;Ljava/util/Map;Ljava/util/Collection;)V
+	public fun content (Ljava/lang/String;)Ljava/util/Map;
+	public fun getContext ()Lhep/dataforge/context/Context;
+	public fun getData ()Lhep/dataforge/data/DataNode;
+	public fun getDefaultChainTarget ()Ljava/lang/String;
+	public fun getDefaultTarget ()Ljava/lang/String;
+	public fun getLogger ()Lmu/KLogger;
+	public fun getTargets ()Ljava/util/Map;
+	public fun getTasks ()Ljava/util/Map;
+	public fun run (Lhep/dataforge/workspace/Task;Lhep/dataforge/meta/Meta;)Lhep/dataforge/data/DataNode;
+}
+
+public final class hep/dataforge/workspace/SimpleWorkspace$Companion {
+}
+
+public final class hep/dataforge/workspace/SimpleWorkspaceBuilder : hep/dataforge/workspace/WorkspaceBuilder {
+	public fun <init> (Lhep/dataforge/context/Context;)V
+	public fun build ()Lhep/dataforge/workspace/SimpleWorkspace;
+	public synthetic fun build ()Lhep/dataforge/workspace/Workspace;
+	public fun getContext ()Lhep/dataforge/context/Context;
+	public fun getData ()Lhep/dataforge/data/DataTreeBuilder;
+	public fun getParentContext ()Lhep/dataforge/context/Context;
+	public fun getTargets ()Ljava/util/Map;
+	public fun getTasks ()Ljava/util/Set;
+	public fun setContext (Lhep/dataforge/context/Context;)V
+	public fun setData (Lhep/dataforge/data/DataTreeBuilder;)V
+	public fun setTargets (Ljava/util/Map;)V
+	public fun setTasks (Ljava/util/Set;)V
+}
+
+public abstract interface class hep/dataforge/workspace/Task : hep/dataforge/context/Named, hep/dataforge/meta/descriptors/Described {
+	public static final field Companion Lhep/dataforge/workspace/Task$Companion;
+	public static final field TYPE Ljava/lang/String;
+	public abstract fun build (Lhep/dataforge/workspace/Workspace;Lhep/dataforge/meta/Meta;)Lhep/dataforge/workspace/TaskModel;
+	public abstract fun getType ()Lkotlin/reflect/KClass;
+	public abstract fun isTerminal ()Z
+	public abstract fun run (Lhep/dataforge/workspace/Workspace;Lhep/dataforge/workspace/TaskModel;)Lhep/dataforge/data/DataNode;
+	public abstract fun validate (Lhep/dataforge/workspace/TaskModel;)V
+}
+
+public final class hep/dataforge/workspace/Task$Companion {
+	public static final field TYPE Ljava/lang/String;
+}
+
+public final class hep/dataforge/workspace/Task$DefaultImpls {
+	public static fun isTerminal (Lhep/dataforge/workspace/Task;)Z
+	public static fun validate (Lhep/dataforge/workspace/Task;Lhep/dataforge/workspace/TaskModel;)V
+}
+
+public final class hep/dataforge/workspace/TaskBuilder {
+	public fun <init> (Lhep/dataforge/names/Name;Lkotlin/reflect/KClass;)V
+	public final fun description (Lkotlin/jvm/functions/Function1;)V
+	public final fun getName ()Lhep/dataforge/names/Name;
+	public final fun getType ()Lkotlin/reflect/KClass;
+	public final fun model (Lkotlin/jvm/functions/Function2;)V
+	public final fun rawTransform (Ljava/lang/String;Ljava/lang/String;Lkotlin/jvm/functions/Function2;)V
+	public static synthetic fun rawTransform$default (Lhep/dataforge/workspace/TaskBuilder;Ljava/lang/String;Ljava/lang/String;Lkotlin/jvm/functions/Function2;ILjava/lang/Object;)V
+	public final fun transform (Lkotlin/reflect/KClass;Ljava/lang/String;Ljava/lang/String;Lkotlin/jvm/functions/Function2;)V
+	public static synthetic fun transform$default (Lhep/dataforge/workspace/TaskBuilder;Lkotlin/reflect/KClass;Ljava/lang/String;Ljava/lang/String;Lkotlin/jvm/functions/Function2;ILjava/lang/Object;)V
+}
+
+public final class hep/dataforge/workspace/TaskBuilder$TaskEnv {
+	public fun <init> (Lhep/dataforge/names/Name;Lhep/dataforge/meta/Meta;Lhep/dataforge/context/Context;Lhep/dataforge/data/DataNode;)V
+	public final fun getContext ()Lhep/dataforge/context/Context;
+	public final fun getData ()Lhep/dataforge/data/DataNode;
+	public final fun getMeta ()Lhep/dataforge/meta/Meta;
+	public final fun getName ()Lhep/dataforge/names/Name;
+	public final fun invoke (Lhep/dataforge/workspace/DirectTaskDependency;)Lhep/dataforge/data/DataNode;
+}
+
+public abstract class hep/dataforge/workspace/TaskDependency : hep/dataforge/workspace/Dependency {
+	public fun <init> (Lhep/dataforge/meta/Meta;Lhep/dataforge/names/Name;)V
+	public synthetic fun <init> (Lhep/dataforge/meta/Meta;Lhep/dataforge/names/Name;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
+	public fun apply (Lhep/dataforge/workspace/Workspace;)Lhep/dataforge/data/DataNode;
+	public final fun getMeta ()Lhep/dataforge/meta/Meta;
+	public abstract fun getName ()Lhep/dataforge/names/Name;
+	public final fun getPlacement ()Lhep/dataforge/names/Name;
+	public abstract fun resolveTask (Lhep/dataforge/workspace/Workspace;)Lhep/dataforge/workspace/Task;
+	public fun toMeta ()Lhep/dataforge/meta/Meta;
+}
+
+public abstract interface class hep/dataforge/workspace/TaskDependencyContainer {
+	public abstract fun add (Lhep/dataforge/workspace/Dependency;)V
+	public abstract fun getDefaultMeta ()Lhep/dataforge/meta/Meta;
+}
+
+public final class hep/dataforge/workspace/TaskModel : hep/dataforge/meta/MetaRepr {
+	public static final field Companion Lhep/dataforge/workspace/TaskModel$Companion;
+	public fun <init> (Lhep/dataforge/names/Name;Lhep/dataforge/meta/Meta;Ljava/util/Collection;)V
+	public final fun component1 ()Lhep/dataforge/names/Name;
+	public final fun component2 ()Lhep/dataforge/meta/Meta;
+	public final fun component3 ()Ljava/util/Collection;
+	public final fun copy (Lhep/dataforge/names/Name;Lhep/dataforge/meta/Meta;Ljava/util/Collection;)Lhep/dataforge/workspace/TaskModel;
+	public static synthetic fun copy$default (Lhep/dataforge/workspace/TaskModel;Lhep/dataforge/names/Name;Lhep/dataforge/meta/Meta;Ljava/util/Collection;ILjava/lang/Object;)Lhep/dataforge/workspace/TaskModel;
+	public fun equals (Ljava/lang/Object;)Z
+	public final fun getDependencies ()Ljava/util/Collection;
+	public final fun getMeta ()Lhep/dataforge/meta/Meta;
+	public final fun getName ()Lhep/dataforge/names/Name;
+	public fun hashCode ()I
+	public fun toMeta ()Lhep/dataforge/meta/Meta;
+	public fun toString ()Ljava/lang/String;
+}
+
+public final class hep/dataforge/workspace/TaskModel$Companion {
+	public final fun getMODEL_TARGET_KEY ()Lhep/dataforge/names/Name;
+}
+
+public final class hep/dataforge/workspace/TaskModelBuilder : hep/dataforge/workspace/TaskDependencyContainer {
+	public fun <init> (Lhep/dataforge/names/Name;Lhep/dataforge/meta/Meta;)V
+	public synthetic fun <init> (Lhep/dataforge/names/Name;Lhep/dataforge/meta/Meta;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
+	public fun add (Lhep/dataforge/workspace/Dependency;)V
+	public final fun build ()Lhep/dataforge/workspace/TaskModel;
+	public fun getDefaultMeta ()Lhep/dataforge/meta/Meta;
+	public final fun getMeta ()Lhep/dataforge/meta/MetaBuilder;
+	public final fun getName ()Lhep/dataforge/names/Name;
+	public final fun getTarget ()Ljava/lang/String;
+	public final fun setMeta (Lhep/dataforge/meta/MetaBuilder;)V
+	public final fun setTarget (Ljava/lang/String;)V
+}
+
+public final class hep/dataforge/workspace/TaskModelKt {
+	public static final fun allData (Lhep/dataforge/workspace/TaskDependencyContainer;Lhep/dataforge/names/Name;)Lhep/dataforge/workspace/AllDataDependency;
+	public static synthetic fun allData$default (Lhep/dataforge/workspace/TaskDependencyContainer;Lhep/dataforge/names/Name;ILjava/lang/Object;)Lhep/dataforge/workspace/AllDataDependency;
+	public static final fun buildInput (Lhep/dataforge/workspace/TaskModel;Lhep/dataforge/workspace/Workspace;)Lhep/dataforge/data/DataTree;
+	public static final fun data (Lhep/dataforge/workspace/TaskDependencyContainer;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)Lhep/dataforge/workspace/DataDependency;
+	public static final fun data (Lhep/dataforge/workspace/TaskDependencyContainer;Lkotlin/jvm/functions/Function1;)Lhep/dataforge/workspace/DataDependency;
+	public static synthetic fun data$default (Lhep/dataforge/workspace/TaskDependencyContainer;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;ILjava/lang/Object;)Lhep/dataforge/workspace/DataDependency;
+	public static final fun dependsOn (Lhep/dataforge/workspace/TaskDependencyContainer;Lhep/dataforge/names/Name;Lhep/dataforge/names/Name;Lhep/dataforge/meta/Meta;)Lhep/dataforge/workspace/WorkspaceTaskDependency;
+	public static final fun dependsOn (Lhep/dataforge/workspace/TaskDependencyContainer;Lhep/dataforge/workspace/Task;Lhep/dataforge/names/Name;Lhep/dataforge/meta/Meta;)Lhep/dataforge/workspace/DirectTaskDependency;
+	public static final fun dependsOn (Lhep/dataforge/workspace/TaskDependencyContainer;Lhep/dataforge/workspace/Task;Lhep/dataforge/names/Name;Lkotlin/jvm/functions/Function1;)Lhep/dataforge/workspace/DirectTaskDependency;
+	public static final fun dependsOn (Lhep/dataforge/workspace/TaskDependencyContainer;Lhep/dataforge/workspace/Task;Ljava/lang/String;Lhep/dataforge/meta/Meta;)Lhep/dataforge/workspace/DirectTaskDependency;
+	public static final fun dependsOn (Lhep/dataforge/workspace/TaskDependencyContainer;Ljava/lang/String;Lhep/dataforge/names/Name;Lhep/dataforge/meta/Meta;)Lhep/dataforge/workspace/WorkspaceTaskDependency;
+	public static synthetic fun dependsOn$default (Lhep/dataforge/workspace/TaskDependencyContainer;Lhep/dataforge/names/Name;Lhep/dataforge/names/Name;Lhep/dataforge/meta/Meta;ILjava/lang/Object;)Lhep/dataforge/workspace/WorkspaceTaskDependency;
+	public static synthetic fun dependsOn$default (Lhep/dataforge/workspace/TaskDependencyContainer;Lhep/dataforge/workspace/Task;Lhep/dataforge/names/Name;Lhep/dataforge/meta/Meta;ILjava/lang/Object;)Lhep/dataforge/workspace/DirectTaskDependency;
+	public static synthetic fun dependsOn$default (Lhep/dataforge/workspace/TaskDependencyContainer;Lhep/dataforge/workspace/Task;Lhep/dataforge/names/Name;Lkotlin/jvm/functions/Function1;ILjava/lang/Object;)Lhep/dataforge/workspace/DirectTaskDependency;
+	public static synthetic fun dependsOn$default (Lhep/dataforge/workspace/TaskDependencyContainer;Lhep/dataforge/workspace/Task;Ljava/lang/String;Lhep/dataforge/meta/Meta;ILjava/lang/Object;)Lhep/dataforge/workspace/DirectTaskDependency;
+	public static synthetic fun dependsOn$default (Lhep/dataforge/workspace/TaskDependencyContainer;Ljava/lang/String;Lhep/dataforge/names/Name;Lhep/dataforge/meta/Meta;ILjava/lang/Object;)Lhep/dataforge/workspace/WorkspaceTaskDependency;
+	public static final fun getTarget (Lhep/dataforge/workspace/TaskModel;)Ljava/lang/String;
+}
+
+public abstract interface class hep/dataforge/workspace/Workspace : hep/dataforge/context/ContextAware, hep/dataforge/provider/Provider {
+	public static final field Companion Lhep/dataforge/workspace/Workspace$Companion;
+	public static final field TYPE Ljava/lang/String;
+	public abstract fun content (Ljava/lang/String;)Ljava/util/Map;
+	public abstract fun getData ()Lhep/dataforge/data/DataNode;
+	public abstract fun getTargets ()Ljava/util/Map;
+	public abstract fun getTasks ()Ljava/util/Map;
+	public abstract fun run (Lhep/dataforge/workspace/Task;Lhep/dataforge/meta/Meta;)Lhep/dataforge/data/DataNode;
+}
+
+public final class hep/dataforge/workspace/Workspace$Companion {
+	public static final field TYPE Ljava/lang/String;
+	public final fun invoke (Lhep/dataforge/context/Context;Lkotlin/jvm/functions/Function1;)Lhep/dataforge/workspace/SimpleWorkspace;
+	public static synthetic fun invoke$default (Lhep/dataforge/workspace/Workspace$Companion;Lhep/dataforge/context/Context;Lkotlin/jvm/functions/Function1;ILjava/lang/Object;)Lhep/dataforge/workspace/SimpleWorkspace;
+}
+
+public final class hep/dataforge/workspace/Workspace$DefaultImpls {
+	public static fun content (Lhep/dataforge/workspace/Workspace;Ljava/lang/String;)Ljava/util/Map;
+	public static fun getDefaultChainTarget (Lhep/dataforge/workspace/Workspace;)Ljava/lang/String;
+	public static fun getDefaultTarget (Lhep/dataforge/workspace/Workspace;)Ljava/lang/String;
+	public static fun getLogger (Lhep/dataforge/workspace/Workspace;)Lmu/KLogger;
+	public static fun run (Lhep/dataforge/workspace/Workspace;Lhep/dataforge/workspace/Task;Lhep/dataforge/meta/Meta;)Lhep/dataforge/data/DataNode;
+}
+
+public abstract interface class hep/dataforge/workspace/WorkspaceBuilder {
+	public abstract fun build ()Lhep/dataforge/workspace/Workspace;
+	public abstract fun getContext ()Lhep/dataforge/context/Context;
+	public abstract fun getData ()Lhep/dataforge/data/DataTreeBuilder;
+	public abstract fun getParentContext ()Lhep/dataforge/context/Context;
+	public abstract fun getTargets ()Ljava/util/Map;
+	public abstract fun getTasks ()Ljava/util/Set;
+	public abstract fun setContext (Lhep/dataforge/context/Context;)V
+	public abstract fun setData (Lhep/dataforge/data/DataTreeBuilder;)V
+	public abstract fun setTargets (Ljava/util/Map;)V
+	public abstract fun setTasks (Ljava/util/Set;)V
+}
+
+public final class hep/dataforge/workspace/WorkspaceBuilderKt {
+	public static final fun context (Lhep/dataforge/workspace/WorkspaceBuilder;Ljava/lang/String;Lkotlin/jvm/functions/Function1;)V
+	public static synthetic fun context$default (Lhep/dataforge/workspace/WorkspaceBuilder;Ljava/lang/String;Lkotlin/jvm/functions/Function1;ILjava/lang/Object;)V
+	public static final fun rawData (Lhep/dataforge/workspace/WorkspaceBuilder;Lhep/dataforge/names/Name;Lkotlin/jvm/functions/Function1;)Lhep/dataforge/data/DataNode;
+	public static synthetic fun rawData$default (Lhep/dataforge/workspace/WorkspaceBuilder;Lhep/dataforge/names/Name;Lkotlin/jvm/functions/Function1;ILjava/lang/Object;)Lhep/dataforge/data/DataNode;
+	public static final fun rawTask (Lhep/dataforge/workspace/WorkspaceBuilder;Ljava/lang/String;Lkotlin/jvm/functions/Function1;)Lhep/dataforge/workspace/Task;
+	public static final fun target (Lhep/dataforge/workspace/WorkspaceBuilder;Ljava/lang/String;Ljava/lang/String;Lkotlin/jvm/functions/Function1;)V
+	public static final fun target (Lhep/dataforge/workspace/WorkspaceBuilder;Ljava/lang/String;Lkotlin/jvm/functions/Function1;)V
+	public static final fun task (Lhep/dataforge/workspace/WorkspaceBuilder;Ljava/lang/String;Lkotlin/reflect/KClass;Lkotlin/jvm/functions/Function1;)Lhep/dataforge/workspace/Task;
+}
+
+public final class hep/dataforge/workspace/WorkspaceKt {
+	public static final fun run (Lhep/dataforge/workspace/Workspace;Lhep/dataforge/workspace/Task;Ljava/lang/String;)Lhep/dataforge/data/DataNode;
+	public static final fun run (Lhep/dataforge/workspace/Workspace;Lhep/dataforge/workspace/Task;Lkotlin/jvm/functions/Function1;)Lhep/dataforge/data/DataNode;
+	public static final fun run (Lhep/dataforge/workspace/Workspace;Ljava/lang/String;Lhep/dataforge/meta/Meta;)Lhep/dataforge/data/DataNode;
+	public static final fun run (Lhep/dataforge/workspace/Workspace;Ljava/lang/String;Ljava/lang/String;)Lhep/dataforge/data/DataNode;
+	public static final fun run (Lhep/dataforge/workspace/Workspace;Ljava/lang/String;Lkotlin/jvm/functions/Function1;)Lhep/dataforge/data/DataNode;
+	public static synthetic fun run$default (Lhep/dataforge/workspace/Workspace;Lhep/dataforge/workspace/Task;Lkotlin/jvm/functions/Function1;ILjava/lang/Object;)Lhep/dataforge/data/DataNode;
+	public static synthetic fun run$default (Lhep/dataforge/workspace/Workspace;Ljava/lang/String;Lkotlin/jvm/functions/Function1;ILjava/lang/Object;)Lhep/dataforge/data/DataNode;
+}
+
+public abstract class hep/dataforge/workspace/WorkspacePlugin : hep/dataforge/context/AbstractPlugin {
+	public fun <init> ()V
+	public fun content (Ljava/lang/String;)Ljava/util/Map;
+	public final fun getTasks ()Ljava/util/Collection;
+	public final fun task (Lhep/dataforge/workspace/Task;)V
+	public final fun task (Ljava/lang/String;Lkotlin/reflect/KClass;Lkotlin/jvm/functions/Function1;)Lhep/dataforge/workspace/GenericTask;
+}
+
+public final class hep/dataforge/workspace/WorkspaceTaskDependency : hep/dataforge/workspace/TaskDependency {
+	public fun <init> (Lhep/dataforge/names/Name;Lhep/dataforge/meta/Meta;Lhep/dataforge/names/Name;)V
+	public fun getName ()Lhep/dataforge/names/Name;
+	public fun resolveTask (Lhep/dataforge/workspace/Workspace;)Lhep/dataforge/workspace/Task;
+}
+
diff --git a/dataforge-workspace/build.gradle.kts b/dataforge-workspace/build.gradle.kts
index c576ef8e..2bb03cec 100644
--- a/dataforge-workspace/build.gradle.kts
+++ b/dataforge-workspace/build.gradle.kts
@@ -1,16 +1,15 @@
 plugins {
-    id("scientifik.mpp")
+    id("ru.mipt.npm.mpp")
+    id("ru.mipt.npm.native")
 }
 
 kotlin {
-    jvm()
-    js()
     sourceSets {
-        val commonMain by getting{
+        commonMain{
             dependencies {
                 api(project(":dataforge-context"))
                 api(project(":dataforge-data"))
-                api(project(":dataforge-output"))
+                api(project(":dataforge-io"))
             }
         }
     }
diff --git a/dataforge-workspace/src/commonMain/kotlin/hep/dataforge/workspace/Dependency.kt b/dataforge-workspace/src/commonMain/kotlin/hep/dataforge/workspace/Dependency.kt
index ed5ab7f0..e58a988b 100644
--- a/dataforge-workspace/src/commonMain/kotlin/hep/dataforge/workspace/Dependency.kt
+++ b/dataforge-workspace/src/commonMain/kotlin/hep/dataforge/workspace/Dependency.kt
@@ -4,6 +4,7 @@ import hep.dataforge.data.DataFilter
 import hep.dataforge.data.DataNode
 import hep.dataforge.data.filter
 import hep.dataforge.meta.Meta
+import hep.dataforge.meta.MetaBuilder
 import hep.dataforge.meta.MetaRepr
 import hep.dataforge.names.Name
 import hep.dataforge.names.asName
@@ -13,11 +14,11 @@ import hep.dataforge.names.plus
 /**
  * A dependency of the task which allows to lazily create a data tree for single dependency
  */
-sealed class Dependency : MetaRepr {
-    abstract fun apply(workspace: Workspace): DataNode<Any>
+public sealed class Dependency : MetaRepr {
+    public abstract fun apply(workspace: Workspace): DataNode<Any>
 }
 
-class DataDependency(val filter: DataFilter, val placement: Name = Name.EMPTY) : Dependency() {
+public class DataDependency(private val filter: DataFilter, private val placement: Name = Name.EMPTY) : Dependency() {
     override fun apply(workspace: Workspace): DataNode<Any> {
         val result = workspace.data.filter(filter)
         return if (placement.isEmpty()) {
@@ -28,34 +29,34 @@ class DataDependency(val filter: DataFilter, val placement: Name = Name.EMPTY) :
     }
 
     override fun toMeta(): Meta = Meta {
-        "data" put filter.config
+        "data" put filter.toMeta()
         "to" put placement.toString()
     }
 }
 
-class AllDataDependency(val placement: Name = Name.EMPTY) : Dependency() {
+public class AllDataDependency(private val placement: Name = Name.EMPTY) : Dependency() {
     override fun apply(workspace: Workspace): DataNode<Any> = if (placement.isEmpty()) {
         workspace.data
     } else {
         DataNode.invoke(Any::class) { this[placement] = workspace.data }
     }
 
-    override fun toMeta() = Meta {
+    override fun toMeta(): MetaBuilder = Meta {
         "data" put "@all"
         "to" put placement.toString()
     }
 }
 
-abstract class TaskDependency<out T : Any>(
-    val meta: Meta,
-    val placement: Name = Name.EMPTY
+public abstract class TaskDependency<out T : Any>(
+    public val meta: Meta,
+    public val placement: Name = Name.EMPTY
 ) : Dependency() {
-    abstract fun resolveTask(workspace: Workspace): Task<T>
+    public abstract fun resolveTask(workspace: Workspace): Task<T>
 
     /**
      * A name of the dependency for logging and serialization
      */
-    abstract val name: Name
+    public abstract val name: Name
 
     override fun apply(workspace: Workspace): DataNode<T> {
         val task = resolveTask(workspace)
@@ -75,8 +76,8 @@ abstract class TaskDependency<out T : Any>(
     }
 }
 
-class DirectTaskDependency<T : Any>(
-    val task: Task<T>,
+public class DirectTaskDependency<T : Any>(
+    public val task: Task<T>,
     meta: Meta,
     placement: Name
 ) : TaskDependency<T>(meta, placement) {
@@ -84,12 +85,12 @@ class DirectTaskDependency<T : Any>(
 
     override val name: Name get() = DIRECT_TASK_NAME + task.name
 
-    companion object {
-        val DIRECT_TASK_NAME = "@direct".asName()
+    public companion object {
+        public val DIRECT_TASK_NAME: Name = "@direct".asName()
     }
 }
 
-class WorkspaceTaskDependency(
+public class WorkspaceTaskDependency(
     override val name: Name,
     meta: Meta,
     placement: Name
diff --git a/dataforge-workspace/src/commonMain/kotlin/hep/dataforge/workspace/GenericTask.kt b/dataforge-workspace/src/commonMain/kotlin/hep/dataforge/workspace/GenericTask.kt
index 4e0ca715..d3844096 100644
--- a/dataforge-workspace/src/commonMain/kotlin/hep/dataforge/workspace/GenericTask.kt
+++ b/dataforge-workspace/src/commonMain/kotlin/hep/dataforge/workspace/GenericTask.kt
@@ -1,8 +1,8 @@
 package hep.dataforge.workspace
 
 import hep.dataforge.data.DataNode
-import hep.dataforge.meta.descriptors.NodeDescriptor
 import hep.dataforge.meta.Meta
+import hep.dataforge.meta.descriptors.NodeDescriptor
 import hep.dataforge.meta.get
 import hep.dataforge.meta.node
 import hep.dataforge.names.Name
@@ -11,7 +11,7 @@ import kotlin.reflect.KClass
 //data class TaskEnv(val workspace: Workspace, val model: TaskModel)
 
 
-class GenericTask<R : Any>(
+public class GenericTask<R : Any>(
     override val name: Name,
     override val type: KClass<out R>,
     override val descriptor: NodeDescriptor,
@@ -19,14 +19,6 @@ class GenericTask<R : Any>(
     private val dataTransform: Workspace.() -> TaskModel.(DataNode<Any>) -> DataNode<R>
 ) : Task<R> {
 
-//    private fun gather(workspace: Workspace, model: TaskModel): DataNode<Any> {
-//        return DataNode.invoke(Any::class) {
-//            model.dependencies.forEach { dep ->
-//                update(dep.apply(workspace))
-//            }
-//        }
-//    }
-
     override fun run(workspace: Workspace, model: TaskModel): DataNode<R> {
         //validate model
         validate(model)
diff --git a/dataforge-workspace/src/commonMain/kotlin/hep/dataforge/workspace/SimpleWorkspace.kt b/dataforge-workspace/src/commonMain/kotlin/hep/dataforge/workspace/SimpleWorkspace.kt
index c94fd8ca..adec8bb9 100644
--- a/dataforge-workspace/src/commonMain/kotlin/hep/dataforge/workspace/SimpleWorkspace.kt
+++ b/dataforge-workspace/src/commonMain/kotlin/hep/dataforge/workspace/SimpleWorkspace.kt
@@ -1,7 +1,7 @@
 package hep.dataforge.workspace
 
 import hep.dataforge.context.Context
-import hep.dataforge.context.content
+import hep.dataforge.context.gather
 import hep.dataforge.context.toMap
 import hep.dataforge.data.DataNode
 import hep.dataforge.meta.Meta
@@ -11,7 +11,7 @@ import hep.dataforge.names.Name
 /**
  * A simple workspace without caching
  */
-class SimpleWorkspace(
+public class SimpleWorkspace(
     override val context: Context,
     override val data: DataNode<Any>,
     override val targets: Map<String, Meta>,
@@ -19,10 +19,10 @@ class SimpleWorkspace(
 ) : Workspace {
 
     override val tasks: Map<Name, Task<*>> by lazy {
-        context.content<Task<*>>(Task.TYPE) + tasks.toMap()
+        context.gather<Task<*>>(Task.TYPE) + tasks.toMap()
     }
 
-    companion object {
+    public companion object {
 
     }
 }
\ No newline at end of file
diff --git a/dataforge-workspace/src/commonMain/kotlin/hep/dataforge/workspace/Task.kt b/dataforge-workspace/src/commonMain/kotlin/hep/dataforge/workspace/Task.kt
index 7511bda9..6792adfa 100644
--- a/dataforge-workspace/src/commonMain/kotlin/hep/dataforge/workspace/Task.kt
+++ b/dataforge-workspace/src/commonMain/kotlin/hep/dataforge/workspace/Task.kt
@@ -2,23 +2,23 @@ package hep.dataforge.workspace
 
 import hep.dataforge.context.Named
 import hep.dataforge.data.DataNode
-import hep.dataforge.meta.descriptors.Described
 import hep.dataforge.meta.Meta
+import hep.dataforge.meta.descriptors.Described
 import hep.dataforge.provider.Type
 import hep.dataforge.workspace.Task.Companion.TYPE
 import kotlin.reflect.KClass
 
 @Type(TYPE)
-interface Task<out R : Any> : Named, Described {
+public interface Task<out R : Any> : Named, Described {
     /**
      * Terminal task is the one that could not build model lazily
      */
-    val isTerminal: Boolean get() = false
+    public val isTerminal: Boolean get() = false
 
     /**
      * The explicit type of the node returned by the task
      */
-    val type: KClass<out R>
+    public val type: KClass<out R>
 
     /**
      * Build a model for this task
@@ -27,14 +27,14 @@ interface Task<out R : Any> : Named, Described {
      * @param taskConfig
      * @return
      */
-    fun build(workspace: Workspace, taskConfig: Meta): TaskModel
+    public fun build(workspace: Workspace, taskConfig: Meta): TaskModel
 
     /**
      * Check if the model is valid and is acceptable by the task. Throw exception if not.
      *
      * @param model
      */
-    fun validate(model: TaskModel) {
+    public fun validate(model: TaskModel) {
         if(this.name != model.name) error("The task $name could not be run with model from task ${model.name}")
     }
 
@@ -46,9 +46,9 @@ interface Task<out R : Any> : Named, Described {
      * @param model - a model to be executed
      * @return
      */
-    fun run(workspace: Workspace, model: TaskModel): DataNode<R>
+    public fun run(workspace: Workspace, model: TaskModel): DataNode<R>
 
-    companion object {
-        const val TYPE = "task"
+    public companion object {
+        public const val TYPE: String = "task"
     }
 }
\ No newline at end of file
diff --git a/dataforge-workspace/src/commonMain/kotlin/hep/dataforge/workspace/TaskBuilder.kt b/dataforge-workspace/src/commonMain/kotlin/hep/dataforge/workspace/TaskBuilder.kt
index 502c669d..4cb48843 100644
--- a/dataforge-workspace/src/commonMain/kotlin/hep/dataforge/workspace/TaskBuilder.kt
+++ b/dataforge-workspace/src/commonMain/kotlin/hep/dataforge/workspace/TaskBuilder.kt
@@ -14,11 +14,11 @@ import kotlin.jvm.JvmName
 import kotlin.reflect.KClass
 
 @DFBuilder
-class TaskBuilder<R : Any>(val name: Name, val type: KClass<out R>) {
+public class TaskBuilder<R : Any>(public val name: Name, public val type: KClass<out R>) {
     private var modelTransform: TaskModelBuilder.(Meta) -> Unit = { allData() }
 
     //    private val additionalDependencies = HashSet<Dependency>()
-    var descriptor: NodeDescriptor? = null
+    private var descriptor: NodeDescriptor? = null
     private val dataTransforms: MutableList<DataTransformation> = ArrayList()
 
     /**
@@ -43,7 +43,7 @@ class TaskBuilder<R : Any>(val name: Name, val type: KClass<out R>) {
 //        additionalDependencies.add(dependency)
 //    }
 
-    fun model(modelTransform: TaskModelBuilder.(Meta) -> Unit) {
+    public fun model(modelTransform: TaskModelBuilder.(Meta) -> Unit) {
         this.modelTransform = modelTransform
     }
 
@@ -51,7 +51,7 @@ class TaskBuilder<R : Any>(val name: Name, val type: KClass<out R>) {
      * Add a transformation on untyped data
      */
     @JvmName("rawTransform")
-    fun transform(
+    public fun transform(
         from: String = "",
         to: String = "",
         block: TaskEnv.(DataNode<*>) -> DataNode<R>
@@ -62,7 +62,7 @@ class TaskBuilder<R : Any>(val name: Name, val type: KClass<out R>) {
         }
     }
 
-    fun <T : Any> transform(
+    public fun <T : Any> transform(
         inputType: KClass<out T>,
         from: String = "",
         to: String = "",
@@ -75,7 +75,7 @@ class TaskBuilder<R : Any>(val name: Name, val type: KClass<out R>) {
         }
     }
 
-    inline fun <reified T : Any> transform(
+    public inline fun <reified T : Any> transform(
         from: String = "",
         to: String = "",
         noinline block: TaskEnv.(DataNode<T>) -> DataNode<R>
@@ -86,7 +86,7 @@ class TaskBuilder<R : Any>(val name: Name, val type: KClass<out R>) {
     /**
      * Perform given action on data elements in `from` node in input and put the result to `to` node
      */
-    inline fun <reified T : Any> action(
+    public inline fun <reified T : Any> action(
         from: String = "",
         to: String = "",
         crossinline block: TaskEnv.() -> Action<T, R>
@@ -96,8 +96,8 @@ class TaskBuilder<R : Any>(val name: Name, val type: KClass<out R>) {
         }
     }
 
-    class TaskEnv(val name: Name, val meta: Meta, val context: Context, val data: DataNode<Any>) {
-        operator fun <T : Any> DirectTaskDependency<T>.invoke(): DataNode<T> = if (placement.isEmpty()) {
+    public class TaskEnv(public val name: Name, public val meta: Meta, public val context: Context, public val data: DataNode<Any>) {
+        public operator fun <T : Any> DirectTaskDependency<T>.invoke(): DataNode<T> = if (placement.isEmpty()) {
             data.cast(task.type)
         } else {
             data[placement].node?.cast(task.type)
@@ -108,7 +108,7 @@ class TaskBuilder<R : Any>(val name: Name, val type: KClass<out R>) {
     /**
      * A customized map action with ability to change meta and name
      */
-    inline fun <reified T : Any> mapAction(
+    public inline fun <reified T : Any> mapAction(
         from: String = "",
         to: String = "",
         crossinline block: MapActionBuilder<T, R>.(TaskEnv) -> Unit
@@ -127,7 +127,7 @@ class TaskBuilder<R : Any>(val name: Name, val type: KClass<out R>) {
     /**
      * A simple map action without changing meta or name
      */
-    inline fun <reified T : Any> map(
+    public inline fun <reified T : Any> map(
         from: String = "",
         to: String = "",
         crossinline block: suspend TaskEnv.(T) -> R
@@ -148,7 +148,7 @@ class TaskBuilder<R : Any>(val name: Name, val type: KClass<out R>) {
     /**
      * Join elements in gathered data by multiple groups
      */
-    inline fun <reified T : Any> reduceByGroup(
+    public inline fun <reified T : Any> reduceByGroup(
         from: String = "",
         to: String = "",
         crossinline block: ReduceGroupBuilder<T, R>.(TaskEnv) -> Unit        //TODO needs KEEP-176
@@ -165,7 +165,7 @@ class TaskBuilder<R : Any>(val name: Name, val type: KClass<out R>) {
     /**
      * Join all elemlents in gathered data matching input type
      */
-    inline fun <reified T : Any> reduce(
+    public inline fun <reified T : Any> reduce(
         from: String = "",
         to: String = "",
         crossinline block: suspend TaskEnv.(Map<Name, T>) -> R
@@ -188,7 +188,7 @@ class TaskBuilder<R : Any>(val name: Name, val type: KClass<out R>) {
     /**
      * Split each element in gathered data into fixed number of fragments
      */
-    inline fun <reified T : Any> split(
+    public inline fun <reified T : Any> split(
         from: String = "",
         to: String = "",
         crossinline block: SplitBuilder<T, R>.(TaskEnv) -> Unit  //TODO needs KEEP-176
@@ -205,16 +205,11 @@ class TaskBuilder<R : Any>(val name: Name, val type: KClass<out R>) {
     /**
      * Use DSL to create a descriptor for this task
      */
-    fun description(transform: NodeDescriptor.() -> Unit) {
+    public fun description(transform: NodeDescriptor.() -> Unit) {
         this.descriptor = NodeDescriptor().apply(transform)
     }
 
     internal fun build(): GenericTask<R> {
-//        val actualTransform: TaskModelBuilder.(Meta) -> Unit = {
-//            modelTransform
-//            dependencies.addAll(additionalDependencies)
-//        }
-
         return GenericTask(
             name,
             type,
diff --git a/dataforge-workspace/src/commonMain/kotlin/hep/dataforge/workspace/TaskModel.kt b/dataforge-workspace/src/commonMain/kotlin/hep/dataforge/workspace/TaskModel.kt
index acd16b2d..5053292e 100644
--- a/dataforge-workspace/src/commonMain/kotlin/hep/dataforge/workspace/TaskModel.kt
+++ b/dataforge-workspace/src/commonMain/kotlin/hep/dataforge/workspace/TaskModel.kt
@@ -21,7 +21,7 @@ import hep.dataforge.workspace.TaskModel.Companion.MODEL_TARGET_KEY
  * @param meta the meta for the task (not for the whole configuration)
  * @param dependencies a list of direct dependencies for this task
  */
-data class TaskModel(
+public data class TaskModel(
     val name: Name,
     val meta: Meta,
     val dependencies: Collection<Dependency>
@@ -45,15 +45,15 @@ data class TaskModel(
         }
     }
 
-    companion object {
-        val MODEL_TARGET_KEY = "@target".asName()
+    public companion object {
+        public val MODEL_TARGET_KEY: Name = "@target".asName()
     }
 }
 
 /**
  * Build input for the task
  */
-fun TaskModel.buildInput(workspace: Workspace): DataTree<Any> {
+public fun TaskModel.buildInput(workspace: Workspace): DataTree<Any> {
     return DataTreeBuilder(Any::class).apply {
         dependencies.forEach { dep ->
             update(dep.apply(workspace))
@@ -61,43 +61,43 @@ fun TaskModel.buildInput(workspace: Workspace): DataTree<Any> {
     }.build()
 }
 
-interface TaskDependencyContainer {
-    val defaultMeta: Meta
-    fun add(dependency: Dependency)
+public interface TaskDependencyContainer {
+    public val defaultMeta: Meta
+    public fun add(dependency: Dependency)
 }
 
 /**
  * Add dependency for a task defined in a workspace and resolved by
  */
-fun TaskDependencyContainer.dependsOn(
+public fun TaskDependencyContainer.dependsOn(
     name: Name,
     placement: Name = Name.EMPTY,
     meta: Meta = defaultMeta
 ): WorkspaceTaskDependency =
     WorkspaceTaskDependency(name, meta, placement).also { add(it) }
 
-fun TaskDependencyContainer.dependsOn(
+public fun TaskDependencyContainer.dependsOn(
     name: String,
     placement: Name = Name.EMPTY,
     meta: Meta = defaultMeta
 ): WorkspaceTaskDependency =
     dependsOn(name.toName(), placement, meta)
 
-fun <T : Any> TaskDependencyContainer.dependsOn(
+public fun <T : Any> TaskDependencyContainer.dependsOn(
     task: Task<T>,
     placement: Name = Name.EMPTY,
     meta: Meta = defaultMeta
 ): DirectTaskDependency<T> =
     DirectTaskDependency(task, meta, placement).also { add(it) }
 
-fun <T : Any> TaskDependencyContainer.dependsOn(
+public fun <T : Any> TaskDependencyContainer.dependsOn(
     task: Task<T>,
     placement: String,
     meta: Meta = defaultMeta
 ): DirectTaskDependency<T> =
     DirectTaskDependency(task, meta, placement.toName()).also { add(it) }
 
-fun <T : Any> TaskDependencyContainer.dependsOn(
+public fun <T : Any> TaskDependencyContainer.dependsOn(
     task: Task<T>,
     placement: Name = Name.EMPTY,
     metaBuilder: MetaBuilder.() -> Unit
@@ -107,13 +107,13 @@ fun <T : Any> TaskDependencyContainer.dependsOn(
 /**
  * Add custom data dependency
  */
-fun TaskDependencyContainer.data(action: DataFilter.() -> Unit): DataDependency =
+public fun TaskDependencyContainer.data(action: DataFilter.() -> Unit): DataDependency =
     DataDependency(DataFilter(action)).also { add(it) }
 
 /**
  * User-friendly way to add data dependency
  */
-fun TaskDependencyContainer.data(pattern: String? = null, from: String? = null, to: String? = null): DataDependency =
+public fun TaskDependencyContainer.data(pattern: String? = null, from: String? = null, to: String? = null): DataDependency =
     data {
         pattern?.let { this.pattern = it }
         from?.let { this.from = it }
@@ -123,17 +123,17 @@ fun TaskDependencyContainer.data(pattern: String? = null, from: String? = null,
 /**
  * Add all data as root node
  */
-fun TaskDependencyContainer.allData(to: Name = Name.EMPTY) = AllDataDependency(to).also { add(it) }
+public fun TaskDependencyContainer.allData(to: Name = Name.EMPTY): AllDataDependency = AllDataDependency(to).also { add(it) }
 
 /**
  * A builder for [TaskModel]
  */
-class TaskModelBuilder(val name: Name, meta: Meta = Meta.EMPTY) : TaskDependencyContainer {
+public class TaskModelBuilder(public val name: Name, meta: Meta = Meta.EMPTY) : TaskDependencyContainer {
     /**
      * Meta for current task. By default uses the whole input meta
      */
-    var meta: MetaBuilder = meta.builder()
-    val dependencies = HashSet<Dependency>()
+    public var meta: MetaBuilder = meta.builder()
+    private val dependencies: HashSet<Dependency> = HashSet<Dependency>()
 
     override val defaultMeta: Meta get() = meta
 
@@ -141,11 +141,11 @@ class TaskModelBuilder(val name: Name, meta: Meta = Meta.EMPTY) : TaskDependency
         dependencies.add(dependency)
     }
 
-    var target: String by this.meta.string(key = MODEL_TARGET_KEY, default = "")
+    public var target: String by this.meta.string(key = MODEL_TARGET_KEY, default = "")
 
 
-    fun build(): TaskModel = TaskModel(name, meta.seal(), dependencies)
+    public fun build(): TaskModel = TaskModel(name, meta.seal(), dependencies)
 }
 
 
-val TaskModel.target get() = meta[MODEL_TARGET_KEY]?.string ?: ""
\ No newline at end of file
+public val TaskModel.target: String get() = meta[MODEL_TARGET_KEY]?.string ?: ""
\ No newline at end of file
diff --git a/dataforge-workspace/src/commonMain/kotlin/hep/dataforge/workspace/Workspace.kt b/dataforge-workspace/src/commonMain/kotlin/hep/dataforge/workspace/Workspace.kt
index ac2b1131..b9aaad18 100644
--- a/dataforge-workspace/src/commonMain/kotlin/hep/dataforge/workspace/Workspace.kt
+++ b/dataforge-workspace/src/commonMain/kotlin/hep/dataforge/workspace/Workspace.kt
@@ -15,23 +15,23 @@ import hep.dataforge.provider.Type
 
 
 @Type(Workspace.TYPE)
-interface Workspace : ContextAware, Provider {
+public interface Workspace : ContextAware, Provider {
     /**
      * The whole data node for current workspace
      */
-    val data: DataNode<Any>
+    public val data: DataNode<Any>
 
     /**
      * All targets associated with the workspace
      */
-    val targets: Map<String, Meta>
+    public val targets: Map<String, Meta>
 
     /**
      * All tasks associated with the workspace
      */
-    val tasks: Map<Name, Task<*>>
+    public val tasks: Map<Name, Task<*>>
 
-    override fun provideTop(target: String): Map<Name, Any> {
+    override fun content(target: String): Map<Name, Any> {
         return when (target) {
             "target", Meta.TYPE -> targets.mapKeys { it.key.toName() }
             Task.TYPE -> tasks
@@ -44,38 +44,36 @@ interface Workspace : ContextAware, Provider {
     /**
      * Invoke a task in the workspace utilizing caching if possible
      */
-    fun <R : Any> run(task: Task<R>, config: Meta): DataNode<R> {
-        context.activate(this)
-        try {
-            val model = task.build(this, config)
-            task.validate(model)
-            return task.run(this, model)
-        } finally {
-            context.deactivate(this)
-        }
+    public fun <R : Any> run(task: Task<R>, config: Meta): DataNode<R> {
+        val model = task.build(this, config)
+        task.validate(model)
+        return task.run(this, model)
     }
 
-    companion object {
-        const val TYPE = "workspace"
-        operator fun invoke(parent: Context = Global, block: SimpleWorkspaceBuilder.() -> Unit): SimpleWorkspace =
+    public companion object {
+        public const val TYPE: String = "workspace"
+        public operator fun invoke(
+            parent: Context = Global,
+            block: SimpleWorkspaceBuilder.() -> Unit,
+        ): SimpleWorkspace =
             SimpleWorkspaceBuilder(parent).apply(block).build()
     }
 }
 
-fun Workspace.run(task: Task<*>, target: String): DataNode<Any> {
-    val meta = targets[target] ?: error("A target with name $target not found in ${this}")
+public fun Workspace.run(task: Task<*>, target: String): DataNode<Any> {
+    val meta = targets[target] ?: error("A target with name $target not found in $this")
     return run(task, meta)
 }
 
 
-fun Workspace.run(task: String, target: String) =
+public fun Workspace.run(task: String, target: String): DataNode<Any> =
     tasks[task.toName()]?.let { run(it, target) } ?: error("Task with name $task not found")
 
-fun Workspace.run(task: String, meta: Meta) =
+public fun Workspace.run(task: String, meta: Meta): DataNode<Any> =
     tasks[task.toName()]?.let { run(it, meta) } ?: error("Task with name $task not found")
 
-fun Workspace.run(task: String, block: MetaBuilder.() -> Unit = {}) =
+public fun Workspace.run(task: String, block: MetaBuilder.() -> Unit = {}): DataNode<Any> =
     run(task, Meta(block))
 
-fun <T: Any> Workspace.run(task: Task<T>, metaBuilder: MetaBuilder.() -> Unit = {}): DataNode<T> =
+public fun <T : Any> Workspace.run(task: Task<T>, metaBuilder: MetaBuilder.() -> Unit = {}): DataNode<T> =
     run(task, Meta(metaBuilder))
\ No newline at end of file
diff --git a/dataforge-workspace/src/commonMain/kotlin/hep/dataforge/workspace/WorkspaceBuilder.kt b/dataforge-workspace/src/commonMain/kotlin/hep/dataforge/workspace/WorkspaceBuilder.kt
index 3bc1ffcf..b7f74079 100644
--- a/dataforge-workspace/src/commonMain/kotlin/hep/dataforge/workspace/WorkspaceBuilder.kt
+++ b/dataforge-workspace/src/commonMain/kotlin/hep/dataforge/workspace/WorkspaceBuilder.kt
@@ -12,25 +12,25 @@ import kotlin.jvm.JvmName
 import kotlin.reflect.KClass
 
 @DFBuilder
-interface WorkspaceBuilder {
-    val parentContext: Context
-    var context: Context
-    var data: DataTreeBuilder<Any>
-    var tasks: MutableSet<Task<Any>>
-    var targets: MutableMap<String, Meta>
+public interface WorkspaceBuilder {
+    public val parentContext: Context
+    public var context: Context
+    public var data: DataTreeBuilder<Any>
+    public var tasks: MutableSet<Task<Any>>
+    public var targets: MutableMap<String, Meta>
 
-    fun build(): Workspace
+    public fun build(): Workspace
 }
 
 
 /**
  * Set the context for future workspcace
  */
-fun WorkspaceBuilder.context(name: String = "WORKSPACE", block: ContextBuilder.() -> Unit = {}) {
-    context = ContextBuilder(name, parentContext).apply(block).build()
+public fun WorkspaceBuilder.context(name: String = "WORKSPACE", block: ContextBuilder.() -> Unit = {}) {
+    context = ContextBuilder(parentContext, name).apply(block).build()
 }
 
-inline fun <reified T : Any> WorkspaceBuilder.data(
+public inline fun <reified T : Any> WorkspaceBuilder.data(
     name: Name = Name.EMPTY,
     noinline block: DataTreeBuilder<T>.() -> Unit
 ): DataNode<T> {
@@ -45,20 +45,20 @@ inline fun <reified T : Any> WorkspaceBuilder.data(
 }
 
 @JvmName("rawData")
-fun WorkspaceBuilder.data(
+public fun WorkspaceBuilder.data(
     name: Name = Name.EMPTY,
     block: DataTreeBuilder<Any>.() -> Unit
 ): DataNode<Any> = data<Any>(name, block)
 
 
-fun WorkspaceBuilder.target(name: String, block: MetaBuilder.() -> Unit) {
+public fun WorkspaceBuilder.target(name: String, block: MetaBuilder.() -> Unit) {
     targets[name] = Meta(block).seal()
 }
 
 /**
  * Use existing target as a base updating it with the block
  */
-fun WorkspaceBuilder.target(name: String, base: String, block: MetaBuilder.() -> Unit) {
+public fun WorkspaceBuilder.target(name: String, base: String, block: MetaBuilder.() -> Unit) {
     val parentTarget = targets[base] ?: error("Base target with name $base not found")
     targets[name] = parentTarget.builder()
         .apply { "@baseTarget" put base }
@@ -66,19 +66,19 @@ fun WorkspaceBuilder.target(name: String, base: String, block: MetaBuilder.() ->
         .seal()
 }
 
-fun <T : Any> WorkspaceBuilder.task(
+public fun <T : Any> WorkspaceBuilder.task(
     name: String,
     type: KClass<out T>,
     builder: TaskBuilder<T>.() -> Unit
 ): Task<T> = TaskBuilder(name.toName(), type).apply(builder).build().also { tasks.add(it) }
 
-inline fun <reified T : Any> WorkspaceBuilder.task(
+public inline fun <reified T : Any> WorkspaceBuilder.task(
     name: String,
     noinline builder: TaskBuilder<T>.() -> Unit
 ): Task<T> = task(name, T::class, builder)
 
 @JvmName("rawTask")
-fun WorkspaceBuilder.task(
+public fun WorkspaceBuilder.task(
     name: String,
     builder: TaskBuilder<Any>.() -> Unit
 ): Task<Any> = task(name, Any::class, builder)
@@ -86,7 +86,7 @@ fun WorkspaceBuilder.task(
 /**
  * A builder for a simple workspace
  */
-class SimpleWorkspaceBuilder(override val parentContext: Context) : WorkspaceBuilder {
+public class SimpleWorkspaceBuilder(override val parentContext: Context) : WorkspaceBuilder {
     override var context: Context = parentContext
     override var data: DataTreeBuilder<Any> = DataTreeBuilder(Any::class)
     override var tasks: MutableSet<Task<Any>> = HashSet()
diff --git a/dataforge-workspace/src/commonMain/kotlin/hep/dataforge/workspace/WorkspacePlugin.kt b/dataforge-workspace/src/commonMain/kotlin/hep/dataforge/workspace/WorkspacePlugin.kt
index a377c023..9079139d 100644
--- a/dataforge-workspace/src/commonMain/kotlin/hep/dataforge/workspace/WorkspacePlugin.kt
+++ b/dataforge-workspace/src/commonMain/kotlin/hep/dataforge/workspace/WorkspacePlugin.kt
@@ -9,22 +9,22 @@ import kotlin.reflect.KClass
 /**
  * An abstract plugin with some additional boilerplate to effectively work with workspace context
  */
-abstract class WorkspacePlugin : AbstractPlugin() {
+public abstract class WorkspacePlugin : AbstractPlugin() {
     private val _tasks = HashSet<Task<*>>()
-    val tasks: Collection<Task<*>> get() = _tasks
+    public val tasks: Collection<Task<*>> get() = _tasks
 
-    override fun provideTop(target: String): Map<Name, Any> {
+    override fun content(target: String): Map<Name, Any> {
         return when (target) {
             Task.TYPE -> tasks.toMap()
             else -> emptyMap()
         }
     }
 
-    fun task(task: Task<*>){
+    public fun task(task: Task<*>){
         _tasks.add(task)
     }
 
-    fun <T : Any> task(
+    public fun <T : Any> task(
         name: String,
         type: KClass<out T>,
         builder: TaskBuilder<T>.() -> Unit
@@ -32,10 +32,10 @@ abstract class WorkspacePlugin : AbstractPlugin() {
         _tasks.add(it)
     }
 
-    inline fun <reified T : Any> task(
+    public inline fun <reified T : Any> task(
         name: String,
         noinline builder: TaskBuilder<T>.() -> Unit
-    ) = task(name, T::class, builder)
+    ): GenericTask<T> = task(name, T::class, builder)
 
 //
 ////TODO add delegates to build gradle-like tasks
diff --git a/dataforge-workspace/src/commonMain/kotlin/hep/dataforge/workspace/envelopeData.kt b/dataforge-workspace/src/commonMain/kotlin/hep/dataforge/workspace/envelopeData.kt
index 248e819c..461409e2 100644
--- a/dataforge-workspace/src/commonMain/kotlin/hep/dataforge/workspace/envelopeData.kt
+++ b/dataforge-workspace/src/commonMain/kotlin/hep/dataforge/workspace/envelopeData.kt
@@ -8,11 +8,11 @@ import kotlin.reflect.KClass
 /**
  * Convert an [Envelope] to a data via given format. The actual parsing is done lazily.
  */
-fun <T : Any> Envelope.toData(type: KClass<out T>, format: IOFormat<T>): Data<T> = Data(type, meta) {
+public fun <T : Any> Envelope.toData(type: KClass<out T>, format: IOFormat<T>): Data<T> = Data(type, meta) {
     data?.readWith(format) ?: error("Can't convert envelope without data to Data")
 }
 
-suspend fun <T : Any> Data<T>.toEnvelope(format: IOFormat<T>): Envelope {
+public suspend fun <T : Any> Data<T>.toEnvelope(format: IOFormat<T>): Envelope {
     val obj = await()
     val binary = format.toBinary(obj)
     return SimpleEnvelope(meta, binary)
diff --git a/dataforge-workspace/src/jvmMain/kotlin/hep/dataforge/workspace/fileData.kt b/dataforge-workspace/src/jvmMain/kotlin/hep/dataforge/workspace/fileData.kt
index 6d16c37d..97ae77e6 100644
--- a/dataforge-workspace/src/jvmMain/kotlin/hep/dataforge/workspace/fileData.kt
+++ b/dataforge-workspace/src/jvmMain/kotlin/hep/dataforge/workspace/fileData.kt
@@ -36,7 +36,7 @@ private fun newZFS(path: Path): FileSystem {
  * @param metaFileFormat the meta format for override
  */
 @DFExperimental
-fun <T : Any> IOPlugin.readDataFile(
+public fun <T : Any> IOPlugin.readDataFile(
     path: Path,
     type: KClass<out T>,
     formatResolver: FileFormatResolver<T>
@@ -47,7 +47,7 @@ fun <T : Any> IOPlugin.readDataFile(
 }
 
 @DFExperimental
-inline fun <reified T : Any> IOPlugin.readDataFile(path: Path): Data<T> =
+public inline fun <reified T : Any> IOPlugin.readDataFile(path: Path): Data<T> =
     readDataFile(path, T::class) { _, _ ->
         resolveIOFormat<T>() ?: error("Can't resolve IO format for ${T::class}")
     }
@@ -56,7 +56,7 @@ inline fun <reified T : Any> IOPlugin.readDataFile(path: Path): Data<T> =
  * Add file/directory-based data tree item
  */
 @DFExperimental
-fun <T : Any> DataTreeBuilder<T>.file(
+public fun <T : Any> DataTreeBuilder<T>.file(
     plugin: IOPlugin,
     path: Path,
     formatResolver: FileFormatResolver<T>
@@ -109,7 +109,7 @@ fun <T : Any> IOPlugin.readDataDirectory(
 }
 
 @DFExperimental
-inline fun <reified T : Any> IOPlugin.readDataDirectory(path: Path): DataNode<T> =
+public inline fun <reified T : Any> IOPlugin.readDataDirectory(path: Path): DataNode<T> =
     readDataDirectory(path, T::class) { _, _ ->
         resolveIOFormat<T>() ?: error("Can't resolve IO format for ${T::class}")
     }
@@ -118,7 +118,7 @@ inline fun <reified T : Any> IOPlugin.readDataDirectory(path: Path): DataNode<T>
  * Write data tree to existing directory or create a new one using default [java.nio.file.FileSystem] provider
  */
 @DFExperimental
-suspend fun <T : Any> IOPlugin.writeDataDirectory(
+public suspend fun <T : Any> IOPlugin.writeDataDirectory(
     path: Path,
     node: DataNode<T>,
     format: IOFormat<T>,
@@ -168,7 +168,7 @@ private suspend fun <T : Any> ZipOutputStream.writeNode(
                 val entry = ZipEntry(name)
                 putNextEntry(entry)
                 envelopeFormat.run {
-                    asOutput().writeObject(envelope)
+                    writeObject(asOutput(), envelope)
                 }
             }
             is DataItem.Node -> {
diff --git a/dataforge-workspace/src/jvmTest/kotlin/hep/dataforge/workspace/FileDataTest.kt b/dataforge-workspace/src/jvmTest/kotlin/hep/dataforge/workspace/FileDataTest.kt
index 6c9537cc..7357c5c5 100644
--- a/dataforge-workspace/src/jvmTest/kotlin/hep/dataforge/workspace/FileDataTest.kt
+++ b/dataforge-workspace/src/jvmTest/kotlin/hep/dataforge/workspace/FileDataTest.kt
@@ -30,12 +30,12 @@ class FileDataTest {
     }
 
     object StringIOFormat : IOFormat<String> {
-        override fun Output.writeObject(obj: String) {
-            writeUtf8String(obj)
+        override fun writeObject(output: Output, obj: String) {
+            output.writeUtf8String(obj)
         }
 
-        override fun Input.readObject(): String {
-            return readUtf8String()
+        override fun readObject(input: Input): String {
+            return input.readUtf8String()
         }
 
         override fun toMeta(): Meta = Meta {
diff --git a/gradle.properties b/gradle.properties
new file mode 100644
index 00000000..a782b701
--- /dev/null
+++ b/gradle.properties
@@ -0,0 +1,9 @@
+kotlin.code.style=official
+kotlin.parallel.tasks.in.project=true
+kotlin.mpp.enableGranularSourceSetsMetadata=true
+//kotlin.native.enableDependencyPropagation=false
+kotlin.mpp.stability.nowarn=true
+
+org.gradle.jvmargs=-XX:MaxMetaspaceSize=512m
+org.gradle.parallel=true
+systemProp.org.gradle.internal.publish.checksums.insecure=true
\ No newline at end of file
diff --git a/gradle/artifactory.gradle b/gradle/artifactory.gradle
deleted file mode 100644
index 12e59642..00000000
--- a/gradle/artifactory.gradle
+++ /dev/null
@@ -1,31 +0,0 @@
-apply plugin: "com.jfrog.artifactory"
-
-artifactory {
-    def artifactory_user = project.hasProperty('artifactoryUser') ? project.property('artifactoryUser') : ""
-    def artifactory_password = project.hasProperty('artifactoryPassword') ? project.property('artifactoryPassword') : ""
-    def artifactory_contextUrl = 'http://npm.mipt.ru:8081/artifactory'
-    
-    contextUrl = artifactory_contextUrl   //The base Artifactory URL if not overridden by the publisher/resolver
-    publish {
-        repository {
-            repoKey = 'gradle-dev-local'
-            username = artifactory_user
-            password = artifactory_password
-        }
-
-        defaults {
-            publications('jvm', 'js', 'kotlinMultiplatform', 'metadata')
-            publishBuildInfo = false
-            publishArtifacts = true
-            publishPom = true
-            publishIvy = false
-        }
-    }
-    resolve {
-        repository {
-            repoKey = 'gradle-dev'
-            username = artifactory_user
-            password = artifactory_password
-        }
-    }
-}
\ No newline at end of file
diff --git a/gradle/bintray.gradle b/gradle/bintray.gradle
deleted file mode 100644
index 8da83c86..00000000
--- a/gradle/bintray.gradle
+++ /dev/null
@@ -1,85 +0,0 @@
-apply plugin: 'com.jfrog.bintray'
-
-def vcs = "https://github.com/mipt-npm/kmath"
-
-def pomConfig = {
-    licenses {
-        license {
-            name "The Apache Software License, Version 2.0"
-            url "http://www.apache.org/licenses/LICENSE-2.0.txt"
-            distribution "repo"
-        }
-    }
-    developers {
-        developer {
-            id "MIPT-NPM"
-            name "MIPT nuclear physics methods laboratory"
-            organization "MIPT"
-            organizationUrl "http://npm.mipt.ru"
-        }
-    }
-    scm {
-        url vcs
-    }
-}
-
-project.ext.configureMavenCentralMetadata = { pom ->
-    def root = asNode()
-    root.appendNode('name', project.name)
-    root.appendNode('description', project.description)
-    root.appendNode('url', vcs)
-    root.children().last() + pomConfig
-}
-
-project.ext.configurePom = pomConfig
-
-
-// Configure publishing
-publishing {
-    repositories {
-        maven {
-            url = "https://bintray.com/mipt-npm/scientifik"
-        }
-    }
-
-    // Process each publication we have in this project
-    publications.all { publication ->
-        // apply changes to pom.xml files, see pom.gradle
-        pom.withXml(configureMavenCentralMetadata)
-
-
-    }
-}
-
-bintray {
-    user = project.hasProperty('bintrayUser') ? project.property('bintrayUser') : System.getenv('BINTRAY_USER')
-    key = project.hasProperty('bintrayApiKey') ? project.property('bintrayApiKey') : System.getenv('BINTRAY_API_KEY')
-    publish = true
-    override = true // for multi-platform Kotlin/Native publishing
-
-    pkg {
-        userOrg = "mipt-npm"
-        repo = "scientifik"
-        name = "scientifik.kmath"
-        issueTrackerUrl = "https://github.com/mipt-npm/kmath/issues"
-        licenses = ['Apache-2.0']
-        vcsUrl = vcs
-        version {
-            name = project.version
-            vcsTag = project.version
-            released = new Date()
-        }
-    }
-}
-
-bintrayUpload.dependsOn publishToMavenLocal
-
-// This is for easier debugging of bintray uploading problems
-bintrayUpload.doFirst {
-    publications = project.publishing.publications.findAll {
-        !it.name.contains('-test') && it.name != 'kotlinMultiplatform'
-    }.collect {
-        println("Uploading artifact '$it.groupId:$it.artifactId:$it.version' from publication '$it.name'")
-        it.name//https://github.com/bintray/gradle-bintray-plugin/issues/256
-    }
-}
\ No newline at end of file
diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar
index 62d4c053..e708b1c0 100644
Binary files a/gradle/wrapper/gradle-wrapper.jar and b/gradle/wrapper/gradle-wrapper.jar differ
diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties
index 622ab64a..12d38de6 100644
--- a/gradle/wrapper/gradle-wrapper.properties
+++ b/gradle/wrapper/gradle-wrapper.properties
@@ -1,5 +1,5 @@
 distributionBase=GRADLE_USER_HOME
 distributionPath=wrapper/dists
-distributionUrl=https\://services.gradle.org/distributions/gradle-6.5-bin.zip
+distributionUrl=https\://services.gradle.org/distributions/gradle-6.6.1-bin.zip
 zipStoreBase=GRADLE_USER_HOME
 zipStorePath=wrapper/dists
diff --git a/gradlew b/gradlew
index fbd7c515..4f906e0c 100755
--- a/gradlew
+++ b/gradlew
@@ -130,7 +130,7 @@ fi
 if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then
     APP_HOME=`cygpath --path --mixed "$APP_HOME"`
     CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
-    
+
     JAVACMD=`cygpath --unix "$JAVACMD"`
 
     # We build the pattern for arguments to be converted via cygpath
diff --git a/gradlew.bat b/gradlew.bat
index 5093609d..107acd32 100644
--- a/gradlew.bat
+++ b/gradlew.bat
@@ -40,7 +40,7 @@ if defined JAVA_HOME goto findJavaFromJavaHome
 
 set JAVA_EXE=java.exe
 %JAVA_EXE% -version >NUL 2>&1
-if "%ERRORLEVEL%" == "0" goto init
+if "%ERRORLEVEL%" == "0" goto execute
 
 echo.
 echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
@@ -54,7 +54,7 @@ goto fail
 set JAVA_HOME=%JAVA_HOME:"=%
 set JAVA_EXE=%JAVA_HOME%/bin/java.exe
 
-if exist "%JAVA_EXE%" goto init
+if exist "%JAVA_EXE%" goto execute
 
 echo.
 echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
@@ -64,21 +64,6 @@ echo location of your Java installation.
 
 goto fail
 
-:init
-@rem Get command-line arguments, handling Windows variants
-
-if not "%OS%" == "Windows_NT" goto win9xME_args
-
-:win9xME_args
-@rem Slurp the command line arguments.
-set CMD_LINE_ARGS=
-set _SKIP=2
-
-:win9xME_args_slurp
-if "x%~1" == "x" goto execute
-
-set CMD_LINE_ARGS=%*
-
 :execute
 @rem Setup the command line
 
@@ -86,7 +71,7 @@ set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
 
 
 @rem Execute Gradle
-"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
+"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %*
 
 :end
 @rem End local scope for the variables with windows NT shell
diff --git a/settings.gradle.kts b/settings.gradle.kts
index e0d250bf..1d15b239 100644
--- a/settings.gradle.kts
+++ b/settings.gradle.kts
@@ -4,34 +4,34 @@ pluginManagement {
         jcenter()
         gradlePluginPortal()
         maven("https://dl.bintray.com/kotlin/kotlin-eap")
-        maven("https://dl.bintray.com/kotlin/kotlinx")
-        maven("https://dl.bintray.com/mipt-npm/scientifik")
+        maven("https://dl.bintray.com/kotlin/kotlin-dev")
+        maven("https://dl.bintray.com/mipt-npm/dataforge")
+        maven("https://dl.bintray.com/mipt-npm/kscience")
         maven("https://dl.bintray.com/mipt-npm/dev")
     }
-    resolutionStrategy {
-        eachPlugin {
-            when (requested.id.id) {
-                "kotlinx-atomicfu" -> useModule("org.jetbrains.kotlinx:atomicfu-gradle-plugin:${requested.version}")
-                "scientifik.mpp", "scientifik.jvm", "scientifik.publish" -> useModule("scientifik:gradle-tools:${requested.version}")
-            }
-        }
+
+    val toolsVersion = "0.7.0"
+    val kotlinVersion = "1.4.20"
+
+    plugins {
+        id("ru.mipt.npm.project") version toolsVersion
+        id("ru.mipt.npm.mpp") version toolsVersion
+        id("ru.mipt.npm.jvm") version toolsVersion
+        id("ru.mipt.npm.js") version toolsVersion
+        id("ru.mipt.npm.publish") version toolsVersion
+        kotlin("jvm") version kotlinVersion
+        kotlin("js") version kotlinVersion
     }
 }
 
-enableFeaturePreview("GRADLE_METADATA")
-
-//rootProject.name = "dataforge-core"
 include(
     ":dataforge-meta",
     ":dataforge-io",
-    ":dataforge-io:dataforge-io-yaml",
+//    ":dataforge-io:dataforge-io-yaml",
     ":dataforge-context",
     ":dataforge-data",
-    ":dataforge-output",
-    ":dataforge-output:dataforge-output-html",
+//    ":dataforge-output",
     ":dataforge-tables",
     ":dataforge-workspace",
     ":dataforge-scripting"
-)
-
-//includeBuild("../kotlinx-io")
\ No newline at end of file
+)
\ No newline at end of file