Metadata-Version: 2.4
Name: sigil-obsidian
Version: 1.3.0
Summary: Schema enforcement and CRUD integrity layer for Obsidian vault folders
Author-email: Gert Schepens <gert@dgtl.be>
License: MIT License
        
        Copyright (c) 2026 Gert Schepens
        
        Permission is hereby granted, free of charge, to any person obtaining a copy
        of this software and associated documentation files (the "Software"), to deal
        in the Software without restriction, including without limitation the rights
        to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
        copies of the Software, and to permit persons to whom the Software is
        furnished to do so, subject to the following conditions:
        
        The above copyright notice and this permission notice shall be included in all
        copies or substantial portions of the Software.
        
        THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
        IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
        FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
        AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
        LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
        OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
        SOFTWARE.
        
Project-URL: Repository, https://gitlab.com/DigitalGert/sigil
Project-URL: Issues, https://gitlab.com/DigitalGert/sigil/-/issues
Keywords: obsidian,schema,validation,agents,cli,markdown
Classifier: Development Status :: 5 - Production/Stable
Classifier: Environment :: Console
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: MIT License
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Topic :: Text Processing :: Markup :: Markdown
Classifier: Topic :: Utilities
Requires-Python: >=3.11
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: typer<1,>=0.12
Requires-Dist: rich<15,>=13
Requires-Dist: pyyaml<7,>=6.0
Requires-Dist: httpx<1,>=0.27
Provides-Extra: dev
Requires-Dist: pytest<9,>=8.0; extra == "dev"
Requires-Dist: pytest-cov<6,>=5.0; extra == "dev"
Requires-Dist: ruff<1,>=0.4; extra == "dev"
Dynamic: license-file

# Sigil

> Schema enforcement and CRUD integrity layer for Obsidian vault folders — built for agents.

[![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](https://gitlab.com/DigitalGert/sigil/-/blob/main/LICENSE)
[![PyPI](https://img.shields.io/pypi/v/sigil-obsidian)](https://pypi.org/project/sigil-obsidian/)
[![Python](https://img.shields.io/pypi/pyversions/sigil-obsidian)](https://pypi.org/project/sigil-obsidian/)

![Sigil](https://gitlab.com/DigitalGert/sigil/-/raw/main/logo_original.png)

---

*Sigil came to life when I saw the notification that the backend I was using for structured data was going to stop working. I realized that that old backend had never really worked decently at all. Half of the time it worked well, the rest of the time, all sorts of chaos happened. It annoyed me at every contact point, and ended up more of a nuisance than a help. Yet, it did fix an important point for me — I need structured data, where the agents working with it can't just forget about the structure and make a big inconsistent mess.*

*I am, like we all are, a big fan of Obsidian vaults, and on a friction level, those really work best for me. It's accessible, readable, and it has that exciting Bases view, that just looks like it'll do magic. Obsidian is spread over all my devices though, so the ample plugins weren't exactly an easy answer either.*

*And the answer is ultimately simple — I just need schema enforcement; an integrity layer for when the agents are writing to my Obsidian vault. (And if I make a mess, they can fix it too.) And I like building things 🙂 So I wrote a briefing, and half a day of agents running, we now have Sigil ready for all of us to escape the dread of having to use anything other than Obsidian. Point your agents here, and enjoy the structure! (And join us in dev and debugging, this is very much an alive project!)*

— **Gert Schepens**

---

```
$ sigil check projects/

✓ projects/ — 12 files checked

  ✗ acme-proposal.md
    · Status: missing (required)
    · Created: invalid format — expected ISO 8601, got "June 3"

  ✗ old-contact.md
    · Title: missing (required)

2 files with violations · 10 files clean
```

## Install

```bash
pip install sigil-obsidian
```

## Usage

```bash
sigil sources                        # see all known vaults and managed folders
sigil init projects/                 # declare a folder as Sigil-managed
sigil schema projects/               # show required fields before writing
sigil create projects/               # create a validated file
sigil check projects/                # audit all files, list violations
sigil check projects/ --fix          # auto-repair what Sigil can
sigil check projects/note.md         # validate a single file
sigil read projects/ --final         # list only records in a final/done state
sigil stats projects/                # counts and breakdowns by schema field
sigil base projects/                 # regenerate Obsidian .base (after moving folder)
```

---

## How it works

Sigil is initialized per-folder. Each managed folder carries a `sigil.schema.md` file that defines the schema for every file in that folder. From there, all reads and writes go through Sigil.

### Initialization

```bash
sigil init /path/to/vault/projects
```

Sigil walks you through schema selection (built-in templates or custom), writes `sigil.schema.md`, and generates an Obsidian Bases view (`📖 overview.base`) scoped to the schema. The folder is registered in `~/.sigil.config`.

Built-in schema templates: `task`, `contact`, `note`, `project`.

Skip Obsidian-specific files with `--no-obsidian`.

### Schema file: `sigil.schema.md`

Each managed folder has one schema file at `<folder>/sigil.schema.md`:

```markdown
---
sigil: https://gitlab.com/DigitalGert/sigil
sigil_version: 1.3.0
sigil_install: pip install sigil-obsidian
sigil_skill: https://gitlab.com/DigitalGert/sigil/-/raw/main/skill.md
---

This folder is managed by Sigil ...

\```json
{
  "filename": "{Title}",
  "fields": {
    "Title":       { "required": true,  "type": "string",   "obsidian_property": true },
    "Status":      { "required": true,  "type": "enum",
                     "values": ["Open", "In Progress", "Done", "Cancelled"],
                     "finals": ["Done", "Cancelled"] },
    "Created":     { "required": false, "type": "datetime", "obsidian_property": true },
    "Description": { "required": false, "type": "text" }
  }
}
\```
```

Fields not listed in the schema are ignored. Fields marked `obsidian_property: true` are written as Obsidian frontmatter properties. Fields without it become `## FieldName` sections in the note body — readable in Obsidian as normal content.

**`filename`** — template for filenames using `{FieldName}` tokens. Dates render as `YYYY-MM-DD`. Plain tokens are filesystem-sanitized (spaces and unicode preserved); `{Field.slug}` produces a lowercase-hyphenated slug. Example: `"{Started}_{Title.slug}"` → `2026-06-01_senior-pm-bnp.md`. If field values are missing, the rename is skipped.

**`finals`** — enum values that represent a terminal state. Used by `sigil read --final` and shown as a separate count in `sigil stats`. Every value in `finals` must also appear in `values`.

**Supported field types:**

| Type | Description |
|------|-------------|
| `string` | Single-line text |
| `text` | Multiline text / body content |
| `integer` | Whole number |
| `float` | Decimal number |
| `boolean` | `true` / `false` |
| `date` | ISO 8601 date — `YYYY-MM-DD` |
| `datetime` | ISO 8601 datetime — `YYYY-MM-DDThh:mm:ss` |
| `enum` | Fixed set of values — requires a `values` array |
| `url` | Valid URL |
| `email` | Valid email address |
| `list` | Array of strings |
| `tags` | Obsidian-style tags — array |
| `reference` | Obsidian `[[wikilink]]` to another note |

### Check

```bash
sigil check projects/            # audit folder
sigil check projects/ --fix      # auto-apply non-destructive fixes
sigil check projects/ --json     # machine-readable output
sigil check projects/note.md     # validate a single file
```

Reports every violation per file with a proposed fix. The `--fix` flag applies fixes that don't require user input — enum fuzzy corrections, file renames, body-field placement, and `sigil_schema` breadcrumbs. Violations requiring a value decision are always surfaced for human or agent input.

**Version gate:** Every `sigil.schema.md` records which Sigil version last wrote it (`sigil_version`). On `check`, Sigil compares installed vs recorded version and warns when the schema was written with a newer release. If network access is available, Sigil also checks PyPI for the latest published version.

### Schema

```bash
sigil schema projects/
sigil schema projects/ --json
```

Shows exactly what data a file must contain to pass validation. Use this before `create` or `update` to know what to provide.

### CRUD

```bash
sigil create projects/ --data '{"Title": "Acme Proposal", "Status": "New"}'
sigil read projects/
sigil read projects/ acme-proposal.md
sigil read projects/ --final            # only records in a final/done state
sigil update projects/ acme-proposal.md --data '{"Status": "Done"}'
sigil delete projects/ acme-proposal.md
```

`create` and `update` enforce the schema. Non-compliant input is rejected with clear, field-level error messages. `read` returns structured content; with `--json` it returns a clean array of file objects. When finals are defined, `--json` output includes `_is_final: true/false` per record.

### Stats

```bash
sigil stats projects/
sigil stats projects/ --json
```

Counts and breakdowns derived from the schema and file contents — total files, files by Status value, files missing a required field, enum distributions with bar charts.

### Sources

```bash
sigil sources
sigil sources --json
```

Lists all vaults and managed folders Sigil knows about, with schema name and file count. The agent's entry point for discovery in a new session.

---

## Config

Global config lives at `~/.sigil.config` (YAML). Created on first `init`.

Multiple vaults are supported, each with an optional human-readable name:

```yaml
debug: false
log_path: ~/debug.log/
vaults:
  - path: /home/user/Documents/Obsidian/Personal
    name: Personal
  - path: /home/user/Documents/Obsidian/Work
    name: Work
managed_folders:
  - path: /home/user/Documents/Obsidian/Personal/projects
    schema: task
    vault: Personal
    initialized: 2026-06-17
```

Override the config location:

```bash
export SIGIL_CONFIG=/path/to/config    # environment variable
sigil --config /path/to/config ...     # per-command flag
```

When running as an agent skill, set `SIGIL_CONFIG` to a path inside the skills folder to keep config portable and isolated.

Enable debug logging (writes dated log files to `log_path`):

```yaml
debug: true
log_path: ~/debug.log/
```

---

## As an agent skill

Sigil is a general-purpose tool — it works from the terminal, in scripts, in CI, or as a skill loaded by any AI agent. It has no dependency on a specific agent platform.

Sigil ships with `skill.md` — a compact command reference that any agent can load as context. Tested with [Claude Code](https://claude.ai/code) and [OpenClaw](https://openclaw.dev), and compatible with any tool that can read a Markdown skill file.

Install or update the skill file:

```bash
# Via sigil (recommended — keeps skill.md in sync with the installed version)
sigil install-skill

# Or to a custom skills directory
sigil install-skill ~/.openclaw/workspace/skills/

# Or manually
curl -o ~/.claude/skills/sigil.md \
  https://gitlab.com/DigitalGert/sigil/-/raw/main/skill.md
```

---

## Output and exit codes

All commands support `--json` for clean, agent-parseable output.

| Exit code | Meaning |
|-----------|---------|
| 0 | Clean — no violations |
| 1 | Violations found |
| 2 | Tool error |

---

## Contributing

This is a live project. Bug reports, schema template ideas, and pull requests are welcome.

- Issues: [gitlab.com/DigitalGert/sigil/-/issues](https://gitlab.com/DigitalGert/sigil/-/issues)
- Built with Python 3.11+, `typer`, `rich`, `pyyaml`, `httpx`

---

## License

MIT — see [LICENSE](LICENSE).
