Installation and Setup
What version of Python do I need?
Python 3.12 or higher. licit uses StrEnum and other features that require 3.12+.
python3.12 --version
# If you don't have it:
# Ubuntu/Debian: sudo apt install python3.12
# macOS: brew install python@3.12
# Windows: download from python.org
Error: “pip install” hangs
If you use a system with multiple Python versions, make sure you use the correct pip:
# Incorrect (may use Python 3.10 or another version)
pip install licit-ai-cli
# Correct
python3.12 -m pip install licit-ai-cli
Error: ModuleNotFoundError: No module named 'licit'
The installation did not complete correctly. Reinstall:
python3.12 -m pip install -e ".[dev]"
Verify that the entry point works:
python3.12 -m licit --version
Configuration
Where does the .licit.yaml file go?
In the root of your project, alongside pyproject.toml or package.json:
my-project/
├── .licit.yaml ← here
├── pyproject.toml
├── src/
└── tests/
Can I use a different name for the config file?
Yes, use the --config option:
licit --config my-config.yaml status
What happens if .licit.yaml has syntax errors?
licit logs a warning and uses the default values. It does not fail with an error.
$ licit --verbose status
# Warning: Failed to parse .licit.yaml: ...
# Using default configuration
Should I commit .licit.yaml?
Yes. It is the team’s shared configuration. Commit .licit.yaml.
Do not commit .licit/provenance.jsonl or .licit/fria-data.json (sensitive data).
Commands
licit fria / licit report do not work
Some commands are registered in the CLI but their full implementation is part of future phases:
| Command | Phase | Current status |
|---|---|---|
trace | 2 | Functional (v0.2.0) |
changelog | 3 | Functional (v0.3.0) |
fria | 4 | Skeleton |
annex-iv | 4 | Skeleton |
report | 6 | Skeleton |
gaps | 6 | Skeleton |
verify | 6 | Skeleton |
The functional commands in v0.3.0 are: init, status, connect, trace, changelog.
licit init does not detect my language/framework
ProjectDetector looks for specific files:
| Language | File searched |
|---|---|
| Python | pyproject.toml, requirements.txt |
| JavaScript | package.json |
| TypeScript | tsconfig.json |
| Go | go.mod |
| Rust | Cargo.toml |
| Java | pom.xml, build.gradle |
| Framework | How it is detected |
|---|---|
| FastAPI | fastapi in pyproject.toml dependencies |
| Flask | flask in pyproject.toml dependencies |
| Django | django in pyproject.toml dependencies |
| React | react in package.json dependencies |
| Next.js | next in package.json dependencies |
| Express | express in package.json dependencies |
If your language or framework is not supported, open an issue.
licit status shows “not collected” for provenance
Run licit trace to analyze the git history and generate provenance data. After running trace, licit status will show the provenance statistics.
licit trace --stats # Analyze and show statistics
licit status # Now shows provenance data
Testing and Development
Tests fail with structlog errors
Make sure tests/conftest.py configures structlog correctly:
import logging
import structlog
structlog.configure(
wrapper_class=structlog.make_filtering_bound_logger(logging.CRITICAL),
cache_logger_on_first_use=False,
)
The most common error is ValueError: I/O operation on closed file when Click’s CliRunner closes stderr and structlog tries to write to it. The solution is to use WriteLoggerFactory() (not PrintLoggerFactory(file=sys.stderr)).
mypy shows errors on future module imports
Imports of future phase modules (such as licit.frameworks.eu_ai_act) use # type: ignore[import-not-found]:
from licit.frameworks.eu_ai_act.fria import ( # type: ignore[import-not-found]
FRIAGenerator,
)
The type: ignore comment must go on the from line, not on the imported name lines. If ruff reformats the import to multiline, verify that the comment remains on the correct line.
Note: Provenance (Phase 2) and changelog (Phase 3) modules are already implemented and are imported without
type: ignore.
ruff reports UP042 on my enums
Use StrEnum instead of (str, Enum):
# ruff UP042 error:
class MyEnum(str, Enum): # ← error
VALUE = "value"
# Correct:
from enum import StrEnum
class MyEnum(StrEnum): # ← correct
VALUE = "value"
How do I run a single test?
# By name
python3.12 -m pytest tests/test_cli.py::TestCLIHelp::test_help -q
# By pattern (keyword)
python3.12 -m pytest tests/ -q -k "test_init"
# By file
python3.12 -m pytest tests/test_core/test_project.py -q
Compliance
Does licit replace a lawyer/compliance consultant?
No. licit is an assistance tool that automates evidence collection and generates reports. Final compliance decisions should be reviewed by qualified professionals.
Is licit’s report sufficient for an EU AI Act audit?
licit’s report is a starting point. It provides structured technical evidence that can complement compliance documentation. For a formal audit, you will need:
- Legal review of the FRIA
- Additional organizational documentation
- Evidence of risk management processes
- Team training records
What if my project is not “high risk” under the EU AI Act?
If your AI system does not fall into the high-risk category, many EU AI Act requirements do not apply. licit allows marking requirements as n/a (not applicable). However, it is good practice to comply with transparency requirements (Art. 13) and human oversight (Art. 14) regardless of the risk classification.
Is OWASP Agentic Top 10 mandatory?
It is not regulation; it is a security best practices framework. However, following the OWASP Agentic Top 10 recommendations significantly reduces security risks when using AI agents in development.
Security
Does licit send data to any server?
No. licit operates 100% locally. There is no telemetry, analytics, or communication with external servers.
Can I use licit in an air-gapped environment?
Yes. licit does not require an internet connection to function. You only need to install the dependencies beforehand.
Is it safe to commit generated reports?
Reports in .licit/reports/ are generally safe to commit. They contain compliance assessments, not sensitive data. However, review the content before pushing to a public repo.
Files you should not commit:
.licit/provenance.jsonl— Contains contributor information.licit/fria-data.json— May contain sensitive FRIA data- Signing keys (
.licit/signing-key)
Known Issues (v0.3.0)
| Issue | Status | Workaround |
|---|---|---|
| Phase 4-7 commands show an error | Expected | Use init, status, connect, trace, changelog |
| Does not detect Go/Rust/Java frameworks | Limitation | Detects the language but not specific frameworks |
| Provenance heuristics may produce false positives | Limitation | Adjust confidence_threshold in config |
| Session reader only supports Claude Code | Limitation | More readers in future phases |
| FRIA is not interactive | Expected | Implementation in Phase 4 |
| Only Markdown format for compliance reports | Expected | JSON/HTML in Phase 6 |
Markdown differ only supports ATX headings (#) | Limitation | Setext headings (===/---) are not detected |
Glossary
| Term | Definition |
|---|---|
| Provenance | Origin and authorship of code (human vs AI) |
| FRIA | Fundamental Rights Impact Assessment (Art. 27 EU AI Act) |
| Annex IV | Technical documentation required by the EU AI Act |
| SARIF | Static Analysis Results Interchange Format — standard format for security findings |
| SBOM | Software Bill of Materials — component inventory |
| Guardrail | Control that limits the behavior of an AI agent |
| Human review gate | Checkpoint that requires human approval |
| Attestation | Cryptographic verification of data integrity |
| Compliance rate | Percentage of requirements met vs total assessable |
| Gap | Discrepancy between the current state and a compliance requirement |