# extract — Extract a Value from Text via Regex and Store It

**Script name:** `extract`

**Script location:** [`scripts/extract.ts`](../../../scripts/extract.ts)

**Invoke:**
```bash
npx --yes tsx .opencode/skills/templating-vault/scripts/extract.ts \
  --source-key KEY --key TARGET --regex PATTERN [OPTIONS]
```

**CRITICAL:** Always invoke the script using bash and the format noted above.

## Synopsis

```
extract.ts (--source-key KEY | --source-file PATH) --key TARGET --regex PATTERN
           [--capture-group N] [--owner ID] [--write-once]
           [--config PATH] [--store-dir SPEC...]
```

The **only way to set literal variables** at non-admin access. The LLM provides a
regex pattern; this script applies it against the source text (stored in the vault
or in a file) and stores the captured value. The LLM never sees or reproduces the
raw value — it only provides the regex.

If the regex does not match, the script returns a descriptive error with context
hints (line count, character count, first 200 chars) so the LLM can fix its regex
without seeing the full source text.

## Arguments

### Required

| Flag | Type | Description |
|------|------|-------------|
| `--source-key KEY` | string | Vault key whose value is the source text (e.g. `prepared.imp-001`) |
| `--source-file PATH` | string | Path to a text file to extract from (alternative to --source-key) |
| `--key TARGET` | string | Dot-separated key where the extracted value is stored |
| `--regex PATTERN` | string | ECMAScript regex pattern to apply to the source text |

Exactly one of `--source-key` or `--source-file` is required.

### Optional

| Flag | Type | Default | Description |
|------|------|---------|-------------|
| `--capture-group N` | integer | 1 | Which regex capture group to store |
| `--owner ID` | string | — | Owner identity for the stored key |
| `--write-once` | flag | false | Lock the target key after this extraction |

## Output (stdout)

Success:
```json
{"extracted": true, "key": "session.forgejo_pat", "stored": true, "value_length": 40}
```

No match (with context hints for regex debugging):
```json
{
  "extracted": false,
  "error": "Regex did not match any text in the source",
  "hints": {
    "source_lines": 10,
    "source_chars": 283,
    "first_200_chars": "Repository base url: https://git.cleverthis.com\n...",
    "regex_used": "bad_pattern (\\d+)"
  }
}
```

## How It Works

1. Reads source text from the vault (by key) or from a file
2. Applies the ECMAScript regex with `m` (multiline) flag
3. Captures the specified group (default: group 1)
4. Validates the extracted value against the target key's metadata (type, custom regex)
5. Stores the value (bypassing literal enforcement since this IS the literal path)
6. Returns success with the value length (not the value itself)

## Self-Correction Loop

When the regex doesn't match, the LLM sees the `hints` in the error output and can
adjust its regex. The loop is:

```
LLM provides regex → script tries → no match → script returns hints
→ LLM corrects regex → script tries again → match → stored
```

The LLM iterates on the regex, never on the value. The source text stays in the
script's domain.

## Usage Examples

```bash
# Extract a PAT from a prepared prompt by vault key
npx --yes tsx .opencode/skills/templating-vault/scripts/extract.ts \
  --source-key prepared.imp-001 \
  --key session.forgejo_pat \
  --regex 'forgejo pat:\s*([a-f0-9]{40})' \
  --store-dir /tmp/globals --store-dir "session:/tmp/my-session"

# Extract from a file
npx --yes tsx .opencode/skills/templating-vault/scripts/extract.ts \
  --source-file /tmp/raw-prompt.txt \
  --key session.forgejo_url \
  --regex 'Repository base url:\s*(https?://\S+)' \
  --store-dir /tmp/globals
```

## Exit Codes

| Code | Meaning |
|------|---------|
| 0 | Success or regex-no-match (check `extracted` field) |
| 1 | Fatal error (missing args, source not found) |

## Dependencies

- Node.js >= 18, `npx tsx`, `js-yaml`
