SHLS (Sebis Hierarchical List Structure) écrit des données structurées sans guillemets, crochets, deux-points ni clés répétées : chaque section nomme ses clés une seule fois, et les enregistrements en dessous ne listent que les valeurs. L’éditeur SHLS affiche le code et, à côté, le bloc de clés et les enregistrements de chaque section. Modifiez valeurs, clés et enregistrements directement là, voyez les problèmes par ligne, convertissez depuis et vers JSON, YAML et CSV, et voyez combien de tokens SHLS économise par rapport à JSON.
Tout fonctionne dans votre navigateur. Les documents ne sont pas envoyés, il n’y a ni inscription ni publicité.
Une section commence par son nom. Son bloc de clés liste les clés, en retrait d’une espace ; les clés d’une liste imbriquée un niveau plus loin. Après exactement une ligne vide suivent les enregistrements : une valeur par ligne, dans l’ordre des clés. Une liste imbriquée a sa propre ligne (sa clé, ou PH comme espace réservé), avec ses enregistrements un niveau plus loin. Toutes les valeurs sont du texte - les convertir en nombres ou en dates revient au programme qui les lit.
Product
Name
Price
Smartphone A1
599.99
Laptop B2
1299.99
Company
Name
Location
Country
City
TechCorp
PH
USA
San Francisco
Les mêmes données en JSON répètent chaque clé dans chaque enregistrement et ont besoin de guillemets, de crochets et de deux-points. SHLS a été conçu pour les modèles d’IA locaux et dans le cloud, où chaque token compte. SHLS by Sebastian Grünwald - le format, ses règles et les classes de référence SHLSDecoder et SHLSEncoder (Python) se trouvent dans le dépôt SHLS sur GitHub.
À gauche, le SHLS en couleurs - sections, clés, valeurs, niveaux d’imbrication et espaces réservés PH. Au milieu, le bloc de clés de chaque section et ses enregistrements, les clés comme étiquettes. Un clic mène au code, le curseur du code marque son enregistrement.
Changez valeurs, clés et noms de section ; ajoutez, dupliquez, déplacez et supprimez enregistrements et clés. Les enregistrements suivent leur bloc de clés : une nouvelle clé reçoit « - » dans chaque enregistrement. Une étape d’annulation chacun.
L’éditeur lit SHLS exactement comme SHLSDecoder et liste ce que celui-ci lirait autrement qu’il n’y paraît : un enregistrement avec une valeur de trop ou de moins, un retrait, des lignes vides après le bloc de clés, une clé en double.
L’onglet Convertir compte les tokens approximatifs de votre SHLS et des mêmes données en JSON : vous voyez l’économie d’un coup d’œil.
Depuis et vers JSON exactement comme SHLSDecoder et SHLSEncoder, YAML, CSV (une section sous forme de tableau) et JSON Lines. Les fichiers JSON, YAML, CSV et JSON Lines s’ouvrent en SHLS.
Gardez autant de documents que vous voulez dans votre navigateur, chacun avec son propre historique d’annulation, et téléchargez-les tous en ZIP.
Toute page https (et localhost) peut intégrer l’éditeur avec une <iframe> et ?embed=1 - sans inscription, sans clé. Intégré, l’éditeur masque ce texte et affiche un bouton Enregistrer. Il y a deux façons de faire entrer et sortir le document.
src= ouvre un fichier (votre serveur doit autoriser CORS), webhook= fait envoyer le document à cette adresse par « Enregistrer » (Ctrl+S). Ajoutez &token=… pour un en-tête Authorization: Bearer … et &auto pour enregistrer après chaque modification.
<iframe src="https://shls.giit.ch/?embed=1&src=https://your-site.com/data/products.shls&webhook=https://your-site.com/save.php"
allow="clipboard-write" style="width:100%;height:800px;border:0"></iframe>
Le webhook reçoit un POST avec du JSON { editor: "shls", event: "save", id, name, content, updated } ; content est le document sous forme de chaîne. Un petit script PHP qui l’enregistre :
<?php
header('Access-Control-Allow-Origin: https://shls.giit.ch');
header('Access-Control-Allow-Headers: Content-Type, Authorization');
header('Access-Control-Allow-Methods: POST, OPTIONS');
if ($_SERVER['REQUEST_METHOD'] === 'OPTIONS') exit;
if (($_SERVER['HTTP_AUTHORIZATION'] ?? '') !== 'Bearer SECRET') { http_response_code(403); exit; }
$d = json_decode(file_get_contents('php://input'), true);
$name = preg_replace('/[^\w\- ]/u', '_', $d['name']);
file_put_contents(__DIR__ . "/data/$name.shls", $d['content']);
echo '{"ok":true}';
L’éditeur annonce shlseditor:ready, votre page répond par shlseditor:load, l’éditeur signale shlseditor:loaded, shlseditor:change lors de vraies modifications et shlseditor:save quand l’utilisateur enregistre. Votre page peut envoyer shlseditor:get (l’état actuel) ou shlseditor:save (appuyer sur Enregistrer). L’enregistrement passe alors par votre propre connexion et votre propre session.
<iframe id="ed" src="https://shls.giit.ch/?embed=1" allow="clipboard-write" style="width:100%;height:800px;border:0"></iframe>
<script>
const ed = document.getElementById('ed');
const ORIGIN = 'https://shls.giit.ch';
addEventListener('message', async e => {
if (e.source !== ed.contentWindow || e.origin !== ORIGIN) return;
const m = e.data;
if (m.type === 'shlseditor:ready') { // l’éditeur est prêt : on lui transmet le document
ed.contentWindow.postMessage({
type: 'shlseditor:load',
name: 'Products',
content: await (await fetch('/data/products.shls')).text()
}, ORIGIN);
}
if (m.type === 'shlseditor:change') document.title = '● not saved'; // une vraie modification
if (m.type === 'shlseditor:save') { // l’utilisateur a cliqué sur "Save"
await fetch('/api/save', { method: 'POST', headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ name: m.name, content: m.content }) });
document.title = 'Saved';
}
});
// Un bouton d’enregistrement sur votre propre page : la réponse arrive sous forme de shlseditor:save
function saveNow() { ed.contentWindow.postMessage({ type: 'shlseditor:get' }, ORIGIN); }
</script>
L’assistant IA dans votre page : il fonctionne aussi dans le cadre. Avec allow="clipboard-write" sur l’iframe, « Copier le prompt » utilise directement le presse-papiers (sinon l’éditeur se rabat sur l’ancienne commande de copie, ou affiche le prompt à copier à la main). Un lien envoyé par l’IA ne peut pas atteindre un éditeur intégré dans un autre site web : l’éditeur demande donc à l’IA et à l’utilisateur de coller toute la réponse de l’IA dans l’éditeur - ou d’ouvrir l’éditeur dans sa propre fenêtre.
window.open("https://shls.giit.ch/?embed=window", "shlseditor-17") ouvre l’éditeur complet dans sa propre fenêtre et échange les mêmes messages avec window.opener. Les liens d’une IA l’y atteignent. shlseditor:load peut aussi transporter context: { host, title, rules } - le prompt de l’IA indique alors où se trouve le document et suit vos règles - et hook: { url, token }, un webhook pour ce seul document, jamais stocké. Fermer la fenêtre avec des modifications non enregistrées envoie shlseditor:closing.
Transmettez à l’éditeur votre propre prompt, une adresse sur votre site et une clé pour cette session de l’éditeur. La boîte de dialogue de l’IA affiche alors « Connecté à » votre site, ce que vous indiquez à l’IA, et le choix modifier le document actuel ou en créer un nouveau ; Copier le prompt assemble le tout. L’IA envoie son résultat avec la clé à votre serveur, et votre page l’ouvre dans l’éditeur - un nouveau document s’ouvre séparément et reste dans le navigateur de l’utilisateur. Une clé par session de l’éditeur : elle reste valable tant que l’éditeur est ouvert, et l’éditeur ne la demande avec shlseditor:key-request que tant qu’il n’en a pas. L’éditeur n’envoie jamais la clé lui-même et ne la stocke jamais ; l’adresse doit être en https sur votre propre hôte ou sur un de ses sous-domaines.
const key = async () => (await fetch('/api/ai-key.php?doc=17')).json(); // une clé par session de l’éditeur
const k = await key();
ed.contentWindow.postMessage({ type: 'shlseditor:load', name: 'Products', content, ai: {
label: 'My Site', prompt: 'Keep every key. Only add records.',
endpoint: 'https://your-site.com/api/ai-result.php', key: k.key } }, ORIGIN);
// retenez l’id de shlseditor:loaded et ignorez change/save/closing portant un autre id
// seulement tant que l’éditeur n’a pas de clé :
if (m.type === 'shlseditor:key-request') { const k = await key(); ed.contentWindow.postMessage({ type: 'shlseditor:ai', key: k.key }, ORIGIN); }
// tant que l’éditeur est ouvert, prévenez votre serveur chaque minute ; fermer l’éditeur ou la page annule la clé
setInterval(() => fetch('/api/ai-key.php?alive=' + k.key.slice(0, 8)), 60000);
// votre serveur a un résultat (polling, SSE …) : target vaut "current" ou "new"
ed.contentWindow.postMessage({ type: 'shlseditor:load', name: 'Products', content: draft, from: 'ai', target }, ORIGIN);
Créez des clés d’au moins 128 bits aléatoires, ne stockez que leur hash, liez chacune à l’utilisateur connecté, au document et à cette session de l’éditeur, créez-en une par session, ne la gardez valable que tant que votre page signale la session comme ouverte, et annulez-la quand l’éditeur ou la page se ferme.
Le protocole complet se trouve dans llms.txt - donnez-le à une IA et elle construit la connexion pour votre système. L’éditeur JSON fonctionne de la même façon avec le préfixe jsoneditor: - json.giit.ch.
SHLS (Sebis Hierarchical List Structure) est un format texte pour données structurées créé par Sebastian Grünwald. Chaque section nomme ses clés une seule fois dans un bloc de clés ; les enregistrements en dessous ne listent que les valeurs, une par ligne, et le retrait montre l’imbrication. Sans guillemets, crochets, deux-points ni clés répétées, les mêmes données demandent bien moins de tokens que JSON - ce qui en fait un bon format pour les modèles d’IA.
Non. L’éditeur fonctionne entièrement dans votre navigateur. Vos documents ne sont jamais envoyés à un serveur, sauf si vous configurez vous-même un webhook vers votre propre serveur.
Oui. L’éditeur lit et écrit SHLS exactement comme SHLSDecoder et SHLSEncoder du dépôt SHLS - le JSON de l’onglet Convertir correspond aux données que donnent les classes Python. Là où elles lisent un document autrement qu’il n’y paraît (un enregistrement avec une valeur de moins, une ligne vide contenant des espaces), l’éditeur le liste comme problème avec sa ligne.
Oui. Cliquez au milieu sur une valeur, une clé ou un nom de section, tapez, et appuyez sur Enter. Les boutons au-dessus des enregistrements ajoutent, dupliquent, déplacent et suppriment enregistrements et clés ; quand vous ajoutez ou supprimez une clé, chaque enregistrement de la section reçoit ou perd sa valeur. Chaque modification est une étape d’annulation.
L’onglet Convertir compte les tokens approximatifs de votre document en SHLS et des mêmes données en JSON. Pour des tableaux d’enregistrements, SHLS demande souvent moins de la moitié des tokens d’un JSON indenté, car les clés ne sont écrites qu’une fois.
Oui. Ouvrez un fichier .json, .yaml, .csv ou .jsonl et il devient du SHLS, écrit comme l’écrit SHLSEncoder ; l’éditeur indique ce que SHLS ne peut pas garder (valeurs vides, valeurs avec des sauts de ligne). L’onglet Convertir et Exporter écrivent du JSON, YAML, CSV, JSON Lines et du texte brut.
Oui, n’importe quelle IA - ChatGPT, Claude, Gemini, Copilot ou l’IA de votre outil de développement. Cliquez sur « Assistant IA », puis sur « Copier le prompt » : le prompt explique SHLS, si bien que toute IA écrit du SHLS valide. L’IA répond par un lien ; cliquez dessus et le document apparaît dans votre éditeur. « Annuler » revient sur chaque modification.
Non. L’éditeur est gratuit, sans publicité et sans inscription.