# CLAUDE.md This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository. ## Project Overview This is a tool for exporting Outline wiki data via API. The script runs inside a Docker container on the `domnet` network to bypass Authentik SSO authentication and access the internal Outline API directly (`http://outline:3000`). ## Usage ```bash # Run the export with tree visualization ./export_with_trees.sh # Preview without exporting (dry run) ./export_with_trees.sh --dry-run # Run with verbose output ./export_with_trees.sh -v ``` ### CLI Options ``` --dry-run, -n Preview what would be exported without writing files --output, -o DIR Output directory (overrides settings.json) --verbose, -v Increase verbosity (-vv for debug) --skip-verify Skip post-export verification --skip-health-check Skip pre-export health check --settings FILE Path to settings file (default: settings.json) ``` ### Running the Python Export Directly ```bash docker run --rm --network domnet \ -v "$(pwd):/work" \ -w /work \ python:3.11-slim \ bash -c "pip install -q requests tqdm && python3 outline_export_fixed.py" # With options docker run --rm --network domnet \ -v "$(pwd):/work" \ -w /work \ python:3.11-slim \ bash -c "pip install -q requests tqdm && python3 outline_export_fixed.py --dry-run" ``` ## Architecture ### Docker Network Integration - Script runs in Docker container attached to `domnet` bridge network - Direct API access to `http://outline:3000` (internal) bypasses SSO - Uses `python:3.11-slim` image with `requests` and `tqdm` dependencies ### Export Flow 1. Fetch collections via `/api/collections.list` 2. Get navigation tree via `/api/collections.documents` (source of truth for hierarchy) 3. Fetch full document content via `/api/documents.info` (with caching) 4. Export recursively maintaining parent-child structure 5. Save metadata (`_collection_metadata.json`) per collection 6. Generate manifest with checksums for verification ### Key Files - `export_with_trees.sh` - Main export script with tree visualization - `outline_export_fixed.py` - Core export logic with `OutlineExporter` class - `settings.json` - API URL and token configuration (contains secrets) - `outline_export/` - Output directory with markdown files and metadata - `outline_backup_*.tar.gz` - Timestamped compressed backups ### Configuration Settings are in `settings.json`: - `source.url` - Internal Docker URL (`http://outline:3000`) - `source.token` - Outline API token - `export.output_directory` - Output path (default: `outline_export`) - `advanced.max_hierarchy_depth` - Prevent infinite recursion (default: 100) ## Important Notes ### Security - `settings.json` contains API token - never commit to git - Backup files may contain sensitive wiki content ### Backup System - Each export automatically backs up previous exports to `outline_backup_YYYYMMDD_HHMMSS.tar.gz` - Old uncompressed export directory is deleted after backup - Backups achieve 90%+ compression on markdown content ### Reliability Features - **Health check**: Verifies API connectivity before export - **Retry logic**: Failed API requests retry up to 3 times with exponential backoff - **Logging**: Structured logging with configurable verbosity levels ### Document Counting The navigation tree (`/api/collections.documents`) is the source of truth for document hierarchy. Document counting is recursive to include all nested children. --- ## Import Tool The import script restores exported markdown files back into Outline, preserving the full document hierarchy. ### Usage ```bash # Import all collections from outline_export/ ./import_to_outline.sh # Preview what would be imported (no changes made) ./import_to_outline.sh --dry-run # Import into a single timestamped collection ./import_to_outline.sh --single # Import from a different directory ./import_to_outline.sh -d exports/ # Overwrite existing collections ./import_to_outline.sh --force ``` ### CLI Options ``` -s, --single Import all into single timestamped collection -n, --dry-run Preview operations without making changes -d, --source DIR Source directory (default: outline_export) -v, --verbose Increase verbosity (-vv for debug) -f, --force Overwrite existing collections (instead of skip) --settings FILE Path to settings file (default: settings.json) -h, --help Show help message ``` ### Import Modes **Collection-per-Folder (Default)** Each subdirectory becomes a separate collection: ``` outline_export/ ├── Bewerbungen/ → Creates "Bewerbungen" collection ├── Projekte/ → Creates "Projekte" collection └── Privat/ → Creates "Privat" collection ``` **Single Collection (`--single`)** All content goes into one timestamped collection: ``` outline_export/ ├── Bewerbungen/ → Becomes parent doc "Bewerbungen" ├── Projekte/ → Becomes parent doc "Projekte" └── Privat/ → Becomes parent doc "Privat" All imported into: "import_20260119_143052" collection ``` ### Import Flow 1. Load `_collection_metadata.json` from each collection directory 2. Build document tree maintaining parent-child relationships 3. Create collections via `/api/collections.create` 4. Create documents via `/api/documents.create` with proper `parentDocumentId` 5. Map old IDs to new IDs to maintain hierarchy 6. Display tree-style progress with status indicators ### Key Files - `import_to_outline.sh` - Bash wrapper with Docker execution - `outline_import.py` - Core import logic with `OutlineImporter` class ### Output Example ``` ════════════════════════════════════════════════════════════ OUTLINE IMPORT ════════════════════════════════════════════════════════════ Source: outline_export/ Target: http://outline:3000 Mode: Collection per folder Checking API connectivity... ✓ Bewerbungen/ (11 documents) Creating collection... ✓ (id: 7f3a...) ├── CV.md ✓ created ├── Tipico.md ✓ created │ ├── Pitch Tipico.md ✓ created │ └── Fragen 3. Runde.md ✓ created └── Ihre PVS.md ✓ created ════════════════════════════════════════════════════════════ SUMMARY ════════════════════════════════════════════════════════════ Collections: 1 created, 0 skipped, 0 errors Documents: 11 created, 0 skipped, 0 errors Duration: 2.3 seconds ════════════════════════════════════════════════════════════ ``` ### Duplicate Handling | Scenario | Default | With `--force` | |----------|---------|----------------| | Collection exists | Skip entire collection | Delete and recreate | | Document exists | Skip document | Update document | ### Error Handling - **API connection failure**: Abort with error message - **Collection creation fails**: Abort that collection, continue others - **Document creation fails**: Log error, continue with siblings - **Missing markdown file**: Log warning, skip document - **Parent not found**: Create as root-level document