forge-tlp
by N4M3Zv0.2.0
TLP file access control — RED/AMBER/GREEN/CLEAR classification, safe-read, blind-metadata. USE WHEN accessing protected files or configuring file access policies.
1 skill GitHub
Documentation
# context-tlp
Traffic Light Protocol (TLP) file access control plugin for Claude Code.
## What It Does
Enforces sensitivity-based file access policies following the [Traffic Light Protocol](https://www.cisa.gov/news-events/news/traffic-light-protocol-tlp-definitions-and-usage).
Files are classified as `RED` (blocked), `AMBER` (requires approval), `GREEN` (open), or `CLEAR` (public) using a `.tlp` config file (YAML syntax) or file metadata.
`AMBER` reads go through `safe-read`, which strips inline `#tlp/red` sections before the AI sees the content.
The convention is based on Obsidian so it can be used directly with your Obsidian vault provided you use the `tlp:` property or the `#tlp/red` tag to redact files.
## Examples
### `.tlp` config
```yaml
RED:
- "*.pdf"
- "Resources/Contacts/**"
AMBER:
- "Resources/Journals/**"
GREEN:
- "Topics/**"
CLEAR:
- ".tlp"
- "CLAUDE.md"
```
### `tlp-guard` — blocking RED files
`tlp-guard` is a [PreToolUse hook](https://docs.anthropic.com/en/docs/claude-code/hooks#pretooluse) that intercepts Read, Edit, and Write tool calls before they execute. Claude Code pipes the tool call as JSON on stdin; the hook resolves the file's TLP level and either allows or blocks it.
Given the `.tlp` config above, `Resources/Contacts/**` is RED. When Claude tries to read a contact file, the hook blocks it:
```bash
$ echo '{"tool_name":"Read","tool_input":{"file_path":"/vault/Resources/Contacts/john.md"}}' \
| tlp-guard
TLP:RED — access blocked for: Resources/Contacts/john.md
$ echo $?
2
```
Write and Edit calls are blocked the same way — no tool call targeting a RED file gets through:
```bash
$ echo '{"tool_name":"Edit","tool_input":{"file_path":"/vault/Resources/Contacts/john.md","old_string":"...","new_string":"..."}}' \
| tlp-guard
TLP:RED — access blocked for: Resources/Contacts/john.md
$ echo $?
2
```
Exit code `2` tells Claude Code to deny the tool call. The AI never sees the file content.
### Inline `#tlp/red` redaction
For AMBER files that contain sensitive sections, `safe-read` strips `#tlp/red` regions before the AI sees the content.
**Source file:**
```markdown
---
tlp: AMBER
---
# Meeting Notes
Discussed project timeline with the team.
#tlp/red
Salary negotiations: offered $150k, counter at $170k.
#tlp/amber
Next steps: finalize budget by Friday.
Contact Alice at [email protected] #tlp/red (personal: 555-0123) #tlp/amber for details.
```
**`safe-read` output:**
```
---
tlp: AMBER
---
# Meeting Notes
Discussed project timeline with the team.
[REDACTED]
Next steps: finalize budget by Friday.
Contact Alice at [email protected] [REDACTED] for details.
```
Block-mode `#tlp/red` sections are replaced with `[REDACTED]`. Inline `#tlp/red` markers redact to the next `#tlp/*` boundary tag or end of line. Any detected secrets (API keys, tokens, credentials) are replaced with `[SECRET REDACTED]` using patterns sourced from [gitleaks](https://github.com/gitleaks/gitleaks).
## Components
- **tlp-guard** (hook) — PreToolUse hook that intercepts Read/Edit/Write
- **safe-read** (CLI) — Reads files with inline `#tlp/red` redaction + secret detection
- **blind-metadata** (CLI) — Bulk YAML frontmatter operations
## Requirements
- Rust toolchain ([rustup.rs](https://rustup.rs)) — binaries build on first use
- A `.tlp` file at the root of each directory tree to protect
## Installation
### From marketplace
```
/plugin marketplace add N4M3Z/forge-plugins
/plugin install context-tlp@forge-plugins
```
### Local testing
```bash
claude --plugin-dir /path/to/Plugins/context-tlp
```
### Post-install
Whitelist the CLI tools in your project or global `settings.local.json`:
```json
{
"permissions": {
"allow": [
"Bash(<plugin-path>/bin/safe-read:*)",
"Bash(<plugin-path>/bin/blind-metadata:*)"
]
}
}
```
## Configuration
Create a `.tlp` file at your directory root. See [examples/tlp.example.yaml](examples/tlp.example.yaml).
### Pattern syntax
Patterns are listed under level headers (`RED:`, `AMBER:`, `GREEN:`, `CLEAR:`) as quoted strings with a `- ` prefix:
| Pattern | Matches | Example |
|---------|---------|---------|
| `*.ext` | Any file with that extension, anywhere in the tree | `"*.pdf"` matches `docs/report.pdf` |
| `dir/**` | All files under a directory (recursive) | `"Contacts/**"` matches `Contacts/john.md` |
| `exact/path.md` | Exact relative path only | `"README.md"` matches only `README.md` at the root |
First match wins. Files not matched by any pattern default to AMBER.
### Frontmatter override
Files can escalate their own protection level via a `tlp:` field in YAML frontmatter:
```yaml
---
tlp: RED
---
```
The effective level is the **more restrictive** of the path-based and frontmatter-based classification. A file can escalate (`GREEN` path + `RED` frontmatter = `RED`) but never downgrade (`AMBER` path + `GREEN` frontmatter = `AMBER`).
### Fail-closed behavior
If `.tlp` exists but cannot be read (permissions, corruption), all files in that vault are treated as `RED` and access is blocked until the config is fixed. This prevents accidental exposure from a broken config.
Files outside any vault (no `.tlp` in any parent directory) are not affected by the hook.
## Architecture
```
Read request
→ tlp-guard-wrapper.sh (builds if needed)
→ tlp-guard binary
→ walks up to .tlp config
→ classifies file (path pattern + frontmatter override)
→ RED: block (exit 2)
→ AMBER + Read: block, suggest safe-read
→ AMBER + Edit/Write: allow + warn
→ GREEN/CLEAR: allow
```
Hooks use bash scripts. Windows users need WSL or Git Bash. Claude Code plugin hooks don't currently support `.bat`/`.ps1` natively.
`safe-read` also checks TLP classification and refuses `RED` files.
## Development
```bash
# Run all tests (unit + integration)
cargo test
# Check for warnings
cargo clippy -- -D warnings
# Build release binaries
cargo build --release
# Format code
cargo fmt
```
### Project structure
```
src/
lib.rs # Library crate (re-exports modules)
tlp/
mod.rs # TLP enum, classify(), pattern matching
tests.rs # Unit tests
vault/
mod.rs # Vault discovery (walk up to .tlp)
tests.rs # Unit tests
redact/
mod.rs # TLP section redaction + secret detection
tests.rs # Unit tests
frontmatter/
mod.rs # YAML frontmatter get/set, .md file listing
tests.rs # Unit tests
bin/
tlp-guard.rs # PreToolUse hook binary
safe-read.rs # Redacting file reader binary
blind-metadata.rs # Frontmatter bulk operations binary
tests/
fixtures/
configs/ # .tlp config fixtures
content/ # .md content fixtures
tlp_guard.rs # Integration tests for tlp-guard
safe_read.rs # Integration tests for safe-read
blind_metadata.rs # Integration tests for blind-metadata
```
## References
- [Claude Code Hooks — PreToolUse](https://docs.anthropic.com/en/docs/claude-code/hooks#pretooluse)
- [gitleaks](https://github.com/gitleaks/gitleaks) — secret detection patterns used by `safe-read`
## License
[EUPL-1.2](LICENSE)