Loading...
Loading...
Query, browse, and analyze Spanish legislation stored as Markdown files with full Git history in the legalize-es repository.
npx skill4agent add aradotso/trending-skills legalize-es-spanish-legislationSkill by ara.so — Daily 2026 Skills collection.
legalize-es.mdBOE-A-1978-31229.mdgrepgit diffgit loggit showgit checkout# Clone the full repo (includes all history)
git clone https://github.com/legalize-dev/legalize-es.git
cd legalize-es
# Shallow clone if you only need current state (much faster)
git clone --depth 1 https://github.com/legalize-dev/legalize-es.git
cd legalize-esspain/spain/
├── BOE-A-1978-31229.md # Constitución Española
├── BOE-A-1995-25444.md # Código Penal
├── BOE-A-2015-11430.md # Estatuto de los Trabajadores
├── BOE-A-2000-323.md # Ley de Enjuiciamiento Civil
└── ... (8,600+ laws)---
titulo: "Constitución Española"
identificador: "BOE-A-1978-31229"
pais: "es"
rango: "constitucion"
fecha_publicacion: "1978-12-29"
ultima_actualizacion: "2024-02-17"
estado: "vigente"
fuente: "https://www.boe.es/eli/es/c/1978/12/27/(1)"
---rangoconstitucionley-organicaleyreal-decreto-leyreal-decreto-legislativoestadovigentederogado# Search law titles in frontmatter
grep -rl "trabajo" spain/ | head -20
# Search for a keyword across all law bodies
grep -rl "huelga" spain/
# Case-insensitive search for a concept
grep -rli "protección de datos" spain/# Find Article 18 of the Constitution
grep -A 20 "Artículo 18" spain/BOE-A-1978-31229.md
# Find an article with context (10 lines before, 30 after)
grep -B 10 -A 30 "Artículo 135" spain/BOE-A-1978-31229.md# If you know the BOE ID
cat spain/BOE-A-1995-25444.md
# Search by partial identifier
ls spain/ | grep "BOE-A-1995"# List all Organic Laws
grep -rl 'rango: "ley-organica"' spain/
# List all currently active laws
grep -rl 'estado: "vigente"' spain/
# List all repealed laws
grep -rl 'estado: "derogado"' spain/# Full reform history of the Spanish Constitution
git log --oneline -- spain/BOE-A-1978-31229.md
# With dates
git log --format="%h %ad %s" --date=short -- spain/BOE-A-1978-31229.md
# With full commit messages (includes reform source URL)
git log -- spain/BOE-A-1978-31229.md# Diff of a specific reform commit
git show 6660bcf -- spain/BOE-A-1978-31229.md
# Diff between two commits
git diff 6660bcf^..6660bcf -- spain/BOE-A-1978-31229.md
# Diff between two dates
git diff $(git rev-list -1 --before="2011-01-01" HEAD) \
$(git rev-list -1 --before="2012-01-01" HEAD) \
-- spain/BOE-A-1978-31229.md# State of the Constitution as of 2010-01-01
git show $(git rev-list -1 --before="2010-01-01" HEAD):spain/BOE-A-1978-31229.md
# Check out law at a specific commit (read-only inspection)
git show abc1234:spain/BOE-A-1978-31229.md# Find which commit introduced "estabilidad presupuestaria"
git log -S "estabilidad presupuestaria" -- spain/BOE-A-1978-31229.md
# Find which commit changed a specific phrase
git log -G "límite de déficit estructural" --oneline -- spain/BOE-A-1978-31229.md#!/bin/bash
# Extract titles and identifiers from all laws
for file in spain/*.md; do
id=$(grep 'identificador:' "$file" | head -1 | sed 's/.*: "//;s/".*//')
title=$(grep 'titulo:' "$file" | head -1 | sed 's/.*: "//;s/".*//')
echo "$id | $title"
done#!/bin/bash
# Laws updated after 2023-01-01
TARGET_DATE="2023-01-01"
grep -rl "ultima_actualizacion:" spain/ | while read file; do
date=$(grep 'ultima_actualizacion:' "$file" | head -1 | grep -o '[0-9]\{4\}-[0-9]\{2\}-[0-9]\{2\}')
if [[ "$date" > "$TARGET_DATE" ]]; then
echo "$date $file"
fi
done | sort -rimport os
import yaml
def parse_law(filepath):
"""Parse a law Markdown file and return frontmatter + body."""
with open(filepath, 'r', encoding='utf-8') as f:
content = f.read()
# Extract YAML frontmatter between --- delimiters
if content.startswith('---'):
parts = content.split('---', 2)
if len(parts) >= 3:
metadata = yaml.safe_load(parts[1])
body = parts[2].strip()
return metadata, body
return {}, content
# Example: list all active laws
laws_dir = 'spain'
active_laws = []
for filename in os.listdir(laws_dir):
if filename.endswith('.md'):
filepath = os.path.join(laws_dir, filename)
meta, body = parse_law(filepath)
if meta.get('estado') == 'vigente':
active_laws.append({
'id': meta.get('identificador'),
'titulo': meta.get('titulo'),
'rango': meta.get('rango'),
'ultima_actualizacion': meta.get('ultima_actualizacion'),
})
# Sort by last update
active_laws.sort(key=lambda x: x['ultima_actualizacion'] or '', reverse=True)
for law in active_laws[:10]:
print(f"{law['ultima_actualizacion']} [{law['rango']}] {law['titulo']}")import subprocess
import json
def get_reform_history(boe_id):
"""Get all commits that modified a law file."""
filepath = f"spain/{boe_id}.md"
result = subprocess.run(
['git', 'log', '--format=%H|%ad|%s', '--date=short', '--', filepath],
capture_output=True, text=True
)
reforms = []
for line in result.stdout.strip().split('\n'):
if line:
hash_, date, subject = line.split('|', 2)
reforms.append({'hash': hash_, 'date': date, 'subject': subject})
return reforms
# Example usage
history = get_reform_history('BOE-A-1978-31229')
for reform in history:
print(f"{reform['date']} {reform['hash'][:7]} {reform['subject']}")import subprocess
def diff_law_versions(boe_id, commit_before, commit_after):
"""Get unified diff between two versions of a law."""
filepath = f"spain/{boe_id}.md"
result = subprocess.run(
['git', 'diff', f'{commit_before}..{commit_after}', '--', filepath],
capture_output=True, text=True
)
return result.stdout
def get_law_at_date(boe_id, date_str):
"""Get the text of a law as it was on a given date (YYYY-MM-DD)."""
filepath = f"spain/{boe_id}.md"
# Find the last commit before date
rev = subprocess.run(
['git', 'rev-list', '-1', f'--before={date_str}', 'HEAD'],
capture_output=True, text=True
).stdout.strip()
if not rev:
return None
content = subprocess.run(
['git', 'show', f'{rev}:{filepath}'],
capture_output=True, text=True
).stdout
return content
# Example: see Constitution before and after 2011 reform
old_text = get_law_at_date('BOE-A-1978-31229', '2011-09-26')
new_text = get_law_at_date('BOE-A-1978-31229', '2011-09-28')
print("Pre-reform length:", len(old_text))
print("Post-reform length:", len(new_text))import os
import re
def search_laws(query, laws_dir='spain', rango=None, estado='vigente'):
"""Search for a regex pattern across all laws."""
results = []
pattern = re.compile(query, re.IGNORECASE)
for filename in os.listdir(laws_dir):
if not filename.endswith('.md'):
continue
filepath = os.path.join(laws_dir, filename)
with open(filepath, 'r', encoding='utf-8') as f:
content = f.read()
# Filter by frontmatter fields
if estado and f'estado: "{estado}"' not in content:
continue
if rango and f'rango: "{rango}"' not in content:
continue
matches = list(pattern.finditer(content))
if matches:
titulo_match = re.search(r'titulo: "([^"]+)"', content)
titulo = titulo_match.group(1) if titulo_match else filename
results.append({
'file': filename,
'titulo': titulo,
'match_count': len(matches),
'first_match_context': content[max(0, matches[0].start()-100):matches[0].end()+100]
})
return sorted(results, key=lambda x: x['match_count'], reverse=True)
# Example: find all active organic laws mentioning "privacidad"
hits = search_laws("privacidad", rango="ley-organica")
for h in hits:
print(f"[{h['match_count']} matches] {h['titulo']}")
print(f" Context: ...{h['first_match_context'].strip()[:150]}...")
print()# 1. Find relevant laws
grep -rl "protección de datos personales" spain/ > relevant_laws.txt
# 2. Get titles of matching files
while read file; do
grep 'titulo:' "$file" | head -1
done < relevant_laws.txt
# 3. Find the primary law (LOPD/GDPR implementation)
grep -rl 'rango: "ley-organica"' spain/ | xargs grep -l "protección de datos" # 1. Find when Article 135 changed (2011 constitutional reform)
git log -S "estabilidad presupuestaria" --oneline -- spain/BOE-A-1978-31229.md
# 2. View the exact changes
git show <commit-hash> -- spain/BOE-A-1978-31229.md
# 3. Read the commit message for official source
git show --format="%B" <commit-hash> | head -10import os, yaml, json
laws = []
for fname in os.listdir('spain'):
if not fname.endswith('.md'):
continue
with open(f'spain/{fname}', 'r', encoding='utf-8') as f:
content = f.read()
if content.startswith('---'):
parts = content.split('---', 2)
if len(parts) >= 3:
meta = yaml.safe_load(parts[1])
meta['filename'] = fname
laws.append(meta)
with open('laws_index.json', 'w', encoding='utf-8') as f:
json.dump(laws, f, ensure_ascii=False, indent=2, default=str)
print(f"Exported {len(laws)} laws")# Use shallow clone for current state only
git clone --depth 1 https://github.com/legalize-dev/legalize-es.git
# Or clone with limited history
git clone --depth 50 https://github.com/legalize-dev/legalize-es.git# Fetch more history
git fetch --deepen=100
# Fetch full history
git fetch --unshallow# Force UTF-8 in git
git config core.quotepath false
git config i18n.logoutputencoding utf-8
# In Python, always open files with encoding='utf-8'# Search by partial title (case-insensitive)
grep -ril "enjuiciamiento civil" spain/ | head -5
# Or search in frontmatter only (faster)
grep -rl "Ley de Enjuiciamiento Civil" spain/fuente: