Install any skill in seconds. Free to start, no credit card required.
Get Started Free →Document creation, format conversion (ODT/DOCX/PDF), mail merge, and automation with LibreOffice Writer.
.claude/skills/lingxling-writer/SKILL.md| Test case | Without → With | Effect | Δ tokens | Δ turns |
|---|---|---|---|---|
| case-05 | ✗→✓ | ▲ Improved | 39% | 0% |
| case-08 | ✗→✓ | ▲ Improved | 72% | 0% |
| case-09 | ✗→✓ | ▲ Improved | 62% | 0% |
| case-12 | ✗→✓ | ▲ Improved | 80% | 0% |
| case-02 | ✓→✓ | = Same ✓ | 34% | 0% |
LibreOffice Writer skill for creating, editing, converting, and automating document workflows using the native ODT (OpenDocument Text) format.
Use this skill when:
bashsoffice --writer template.odt
pythonimport uno def create_document(): local_ctx = uno.getComponentContext() resolver = local_ctx.ServiceManager.createInstanceWithContext( "com.sun.star.bridge.UnoUrlResolver", local_ctx ) ctx = resolver.resolve( "uno:socket,host=localhost,port=8100;urp;StarOffice.ComponentContext" ) smgr = ctx.ServiceManager doc = smgr.createInstanceWithContext("com.sun.star.text.TextDocument", ctx) text = doc.Text cursor = text.createTextCursor() text.insertString(cursor, "Hello from LibreOffice Writer!", 0) doc.storeToURL("file:///path/to/document.odt", ()) doc.close(True)
pythonfrom odf.opendocument import OpenDocumentText from odf.text import P, H doc = OpenDocumentText() h1 = H(outlinelevel='1', text='Document Title') doc.text.appendChild(h1) doc.save("document.odt")
bash# ODT to DOCX soffice --headless --convert-to docx document.odt # ODT to PDF soffice --headless --convert-to pdf document.odt # DOCX to ODT soffice --headless --convert-to odt document.docx # Batch convert for file in *.odt; do soffice --headless --convert-to pdf "$file" done
pythonimport subprocess import tempfile from pathlib import Path def generate_from_template(template_path, variables, output_path): with tempfile.TemporaryDirectory() as tmpdir: subprocess.run(['unzip', '-q', template_path, '-d', tmpdir]) content_file = Path(tmpdir) / 'content.xml' content = content_file.read_text() for key, value in variables.items(): content = content.replace(f'${{{key}}}', str(value)) content_file.write_text(content) subprocess.run(['zip', '-rq', output_path, '.'], cwd=tmpdir) return output_path
bashsoffice --headless soffice --headless --convert-to <format> <file> soffice --writer # Writer soffice --calc # Calc soffice --impress # Impress soffice --draw # Draw
bashpip install odfpy # ODF manipulation pip install ezodf # Easier ODF handling
bashkillall soffice.bin soffice --headless --accept="socket,host=localhost,port=8100;urp;"
bashsoffice --headless --convert-to pdf:writer_pdf_Export document.odt
| Case | Status | Duration (ms) | Turns | Tokens | Tool calls | ||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| Without | With | Δ | Without | With | Δ | Without | With | Δ | Without | With | Δ | ||
case-01 | fail→fail | 19,099 | 18,654 | -2% | 1 | 1 | 0% | 3,485 | 4,195 | +20% | 0 | 0 | — |
case-02 | pass→pass | 16,333 | 11,271 | -31% | 1 | 1 | 0% | 2,234 | 2,986 | +34% | 0 | 0 | — |
case-03 | pass→pass | 14,277 | 13,835 | -3% | 1 | 1 | 0% | 2,316 | 3,315 | +43% | 0 | 0 | — |
case-04 | pass→pass | 15,766 | 12,385 | -21% | 1 | 1 | 0% | 2,244 | 3,410 | +52% | 0 | 0 | — |
case-05 | fail→pass | 13,456 | 8,760 | -35% | 1 | 1 | 0% | 1,878 | 2,618 | +39% | 0 | 0 | — |
case-06 | fail→fail | 15,925 | 13,819 | -13% | 1 | 1 | 0% | 2,457 | 3,447 | +40% | 0 | 0 | — |
case-07 | pass→pass | 11,879 | 8,707 | -27% | 1 | 1 | 0% | 2,157 | 2,974 | +38% | 0 | 0 | — |
case-08 | fail→pass | 10,901 | 9,242 | -15% | 1 | 1 | 0% | 1,719 | 2,949 | +72% | 0 | 0 | — |
case-09 | fail→pass | 9,853 | 5,590 | -43% | 1 | 1 | 0% | 1,446 | 2,336 | +62% | 0 | 0 | — |
case-10 | pass→pass | 15,430 | 9,864 | -36% | 1 | 1 | 0% | 2,160 | 2,821 | +31% | 0 | 0 | — |
case-11 | pass→pass | 6,644 | 3,536 | -47% | 1 | 1 | 0% | 914 | 1,788 | +96% | 0 | 0 | — |
case-12 | fail→pass | 7,754 | 4,946 | -36% | 1 | 1 | 0% | 1,174 | 2,116 | +80% | 0 | 0 | — |
case-13 | pass→pass | 14,075 | 11,022 | -22% | 1 | 1 | 0% | 2,021 | 3,083 | +53% | 0 | 0 | — |
case-14 | pass→pass | 7,408 | 5,812 | -22% | 1 | 1 | 0% | 1,348 | 2,166 | +61% | 0 | 0 | — |
case-15 | pass→pass | 13,458 | 13,127 | -2% | 1 | 1 | 0% | 2,119 | 3,486 | +65% | 0 | 0 | — |
case-16 | pass→pass | 6,191 | 4,931 | -20% | 1 | 1 | 0% | 731 | 2,035 | +178% | 0 | 0 | — |
case-17 | pass→pass | 7,443 | 6,169 | -17% | 1 | 1 | 0% | 1,095 | 2,362 | +116% | 0 | 0 | — |
case-18 | pass→pass | 5,714 | 5,965 | +4% | 1 | 1 | 0% | 872 | 2,145 | +146% | 0 | 0 | — |
case-19 | pass→pass | 11,110 | 5,919 | -47% | 1 | 1 | 0% | 1,707 | 2,426 | +42% | 0 | 0 | — |
case-20 | pass→pass | 21,518 | 13,183 | -39% | 1 | 1 | 0% | 3,329 | 3,511 | +5% | 0 | 0 | — |
case-21 | pass→pass | 20,420 | 17,987 | -12% | 1 | 1 | 0% | 2,693 | 4,385 | +63% | 0 | 0 | — |
case-22 | pass→pass | 12,436 | 11,314 | -9% | 1 | 1 | 0% | 2,164 | 3,416 | +58% | 0 | 0 | — |
DecimalAI ran this skill against gemini-3.6-flash twice over the same eval suite — once with the skill loaded and once without — and compared the two runs case by case. 22 cases were attempted. The headline lift of +18 percentage points is the difference between those two pass rates over the 22 comparable cases.
Without the skill loaded, the model failed this case. With it loaded, the same prompt on the same model passed. This is one improved case from the latest verified run; every case, including any that regressed, is in the table above.
Other measured skills in the registry, with their headline benchmark lift.