inkd-cli 0.1.1.dev23
Contract-driven autonomous skill harness for an Obsidian-style vault
Requires Python: >=3.10

# inkd

`inkd` is a contract-driven skill runner for a local vault. You bring your own skills; `inkd` discovers, schedules, executes, and tracks them.

## What It Does

- Discovers skills from `<skills_dir>/*/SKILL.md`.
- Loads optional per-skill contracts from `<skills_dir>/*/contract.json`.
- Runs skills manually (`inkd run`) or on triggers (`inkd tick`).
- Supports dependency and follow-up chains (`depends_on`, `followed_by`).
- Stores run history, prompt snapshots, and agent logs.
- Exposes observability commands (`log`, `runs`, `stats`, `doctor`).

## Requirements

- Python `>=3.10`
- Anthropic Agent SDK credentials/environment (for skill execution)
- Optional: `claude` CLI in `PATH` for `inkd chat`

## Install

```bash
pip install -e .
```

## Quick Start

```bash
# 1) First-run setup (writes config.json)
inkd config

# 2) Inspect discovered skills
inkd skills list --verbose

# 3) Run one skill now
inkd run weekly-review --reason "manual run"

# 4) Evaluate scheduled triggers once
inkd tick

# 5) Inspect recent activity
inkd log --limit 20
inkd stats --days 14
```

## Skill Layout

```text
skills/
  weekly-review/
    SKILL.md
    contract.json   # optional
```

Minimal `SKILL.md`:

```md
---
name: weekly-review
description: Summarize weekly progress and blockers.
---

Write the report to `notes/weekly.md`.
```

Example `contract.json`:

```json
{
  "version": 1,
  "enabled": true,
  "risk_level": "medium",
  "triggers": [
    { "type": "cron", "expr": "0 9 * * 1", "reason": "weekly schedule" }
  ],
  "depends_on": [{ "skill": "collect-metrics", "max_age_minutes": 120 }],
  "followed_by": [{ "skill": "publish-report", "on": "success" }],
  "default_payload": { "audience": "team" },
  "executor": {
    "type": "anthropic_agent_sdk",
    "timeout_seconds": 1800,
    "options": {}
  },
  "permissions": {
    "mode": "enforcing",
    "read": ["notes/**", "data/**"],
    "write": ["notes/**"]
  },
  "context": {}
}
```

Notes:

- `executor.type` currently supports `anthropic_agent_sdk`.
- `permissions.mode` is `permissive` by default; `enforcing` is default-deny.

## Configuration

`inkd config` writes JSON like:

```json
{
  "vault_root": "/absolute/path/to/vault",
  "skills_dir": "/absolute/path/to/vault/skills",
  "agent_timeout_seconds": 1800,
  "agent_options": {
    "permission_mode": "acceptEdits"
  }
}
```

Environment variables:

- `INKD_ROOT`: override runtime root (legacy: `VAULT_ROOT`)
- `INKD_CONFIG_PATH`: explicit config file path
- `INKD_SKILLS_DIR`: explicit skills directory (absolute or relative to root)
- `INKD_DATA_DIR`: override runtime data directory

Runtime root resolution order:

1. `INKD_ROOT` (or `VAULT_ROOT`)
2. `vault_root` from `<cwd>/config.json`
3. `vault_root` from user config
4. nearest parent with `skills/` or `config.json`
5. current working directory

User config default path:

- macOS: `~/Library/Application Support/inkd/config.json`
- Linux: `$XDG_CONFIG_HOME/inkd/config.json` or `~/.config/inkd/config.json`
- Windows: `%APPDATA%\\inkd\\config.json`

## Commands

```bash
inkd config
inkd config --show
inkd config --vault-root /path/to/vault --skills-dir /path/to/skills

inkd skills list [--verbose]
inkd skills show <skill>
inkd skills graph
inkd skills enable <skill>
inkd skills disable <skill>
inkd skills new <name>

inkd run <skill> [--reason TEXT] [--start YYYY-MM-DD] [--end YYYY-MM-DD] [--dry-run]
inkd tick [--now ISO-8601] [--dry-run]

inkd log [--limit N]
inkd runs show <run_id> [--raw]
inkd runs grep <pattern> [--limit N] [--scan N] [-i]
inkd stats [--days N] [--skill NAME] [--json]
inkd doctor

inkd chat [session]
inkd chat --list
inkd chat --delete <session>

inkd llm catalog [--json]
```

## Runtime Data

Runtime data is stored outside the repo:

- macOS: `~/Library/Application Support/inkd/`
- Linux: `$XDG_DATA_HOME/inkd/` or `~/.local/share/inkd/`
- Windows: `%APPDATA%\\inkd\\`

Key artifacts:

- `state/runs.db`: run history, trigger state, chat sessions
- `runs/*-prompt.md`: prompt snapshots
- `runs/*-agent.log`: extracted output and raw agent messages

## Shell Completion

```bash
# zsh
eval "$(_INKD_COMPLETE=zsh_source inkd)"

# bash
eval "$(_INKD_COMPLETE=bash_source inkd)"
```

```fish
# fish
eval (env _INKD_COMPLETE=fish_source inkd)
```

## Scheduling On macOS (launchd)

1. Copy `launchd/com.inkd.tick.plist` to `~/Library/LaunchAgents/com.inkd.tick.plist`.
2. Replace `__INKD_BIN__`, `__INKD_ROOT__`, and `__USER__`.
3. Load it:

```bash
launchctl unload ~/Library/LaunchAgents/com.inkd.tick.plist 2>/dev/null || true
launchctl load ~/Library/LaunchAgents/com.inkd.tick.plist
launchctl start com.inkd.tick
```

## Runtime Semantics

Execution guarantees and trigger semantics are documented in `docs/harness-semantics.md`.