---
since: 1.0.0
---
# astwire โ Security and Privacy
astwire is designed around a **fully local execution model**. Target resolution, AST parsing, skeletonization, waste analysis, redaction, partitioning, and formatting all happen on the machine running the binary. astwire makes no network requests of its own โ the only external boundary is what you do with the output file afterward (for example, pasting it into a hosted LLM chat).
## Security and Privacy Architecture
```mermaid
flowchart TD
A["๐ Local Codebase"]
A --> B["๐ฏ Target Resolution
.gitignore / .astwireignore / skip patterns"]
B --> C["๐ Read file content
local disk only"]
C --> D["๐ก๏ธ Transform Pipeline
skeleton โ strip-waste"]
D --> E["๐ Secret Redaction
always applied, before output"]
E --> F{"Redaction pattern match?"}
F -->|Yes| G["[REDACTED:SECRET]
replaces the matched span"]
F -->|No| H["Content passes through unchanged"]
G --> I["๐ฆ FileRecord
local in-memory"]
H --> I
I --> J["โ๏ธ Partition + Format"]
J --> K["๐พ Local Output File(s)
context.md / .xml / .json"]
K --> L{"What do you do
with the output?"}
L -->|"Paste into a hosted LLM"| M["โ ๏ธ Third-party provider boundary
outside astwire's control"]
L -->|"Keep local / commit to a private repo"| N["โ
Stays on this machine"]
O["๐ซ astwire never does"]
O -.-> P["Execute the analyzed code"]
O -.-> Q["Make network requests"]
O -.-> R["Upload source to any service"]
O -.-> S["Write telemetry / usage logs"]
classDef sensitive fill:#fff0f0,stroke:#d64545,stroke-width:2px,color:#5c2020
classDef security fill:#fff4df,stroke:#d59a2a,stroke-width:2px,color:#5c420b
classDef local fill:#e8f7f1,stroke:#2b9a78,stroke-width:2px,color:#174d3d
classDef external fill:#eeeaff,stroke:#7957c7,stroke-width:2px,color:#382568
classDef safe fill:#e8f1ff,stroke:#4a78c2,stroke-width:2px,color:#172b4d
classDef never fill:#f5f3ed,stroke:#777777,stroke-width:1px,color:#444444
class A sensitive
class B,C,D,E,F security
class G,H,I,J,K,N local
class M external
class L safe
class O,P,Q,R,S never
```
## 1. Local Execution Guarantee
Every stage in the pipeline โ target resolution, `ast.parse()`, skeleton transformation, whitespace cleansing, secret redaction, tokenization, partitioning, and formatting โ runs as pure local computation:
- astwire performs static analysis via Python's standard-library `ast` module. It **never executes, imports, or evaluates** the code it analyzes.
- astwire makes **no outbound network calls**. There is no telemetry, no update check, and no usage reporting built into the CLI itself.
- Output is written only to the local filesystem, at the path given by `-o`/`--output` (default `context.xml`).
The only way code content leaves the local machine is if *you* take the generated output file and paste, upload, or otherwise transmit it somewhere โ for example, into a hosted LLM's chat interface. That transmission is outside astwire's control and is governed by whatever service receives it.
## 2. Secret Redaction
`redact_secrets()` (`redact.py`) runs unconditionally on every file's content โ it is **not** gated behind a flag, unlike `--skeleton` or `--strip-waste`.
It matches four regex patterns, in this order:
| Pattern name | Matches |
| --- | --- |
| AWS Key | `aws_access_key_id = "..."` with a 20-character uppercase/digit value |
| Generic API Key | `(api_key\|api-key\|secret\|token\|password) [:=] "..."` with a 16+ character alphanumeric/`_`/`-` value |
| Bearer Token | `Bearer <20+ char token>` (case-insensitive) |
| Private Key Block | `-----BEGIN ... PRIVATE KEY-----` header lines |
Every match is replaced with the literal string `[REDACTED:SECRET]`.
> **Important โ this is best-effort redaction, not a complete secret scanner.** The generic pattern requires a recognizable key name (`api_key`, `secret`, `token`, `password`) immediately followed by `:`/`=` and a quoted value of at least 16 characters. A credential under a different variable name, split across lines, base64-encoded, or embedded in a data structure the regex doesn't match will pass through unredacted. Review generated output before sharing it with a third party, especially for code that legitimately handles credentials.
Redaction happens **after** skeletonization and waste-stripping but is applied to the content as it exists at write time โ so a secret embedded inside a function body that gets skeletonized away by `--skeleton` never reaches the redaction step at all (it simply isn't in the output).
## 3. Gitignore and Ignore-File Compliance
Target resolution honors nested `.gitignore` and `.astwireignore` files via `IgnoreEngine` (`gitignore.py`), using [`pathspec`](https://github.com/cpburnz/python-pathspec)'s `gitignore`-syntax matcher. This means files your project already excludes from version control (`.env`, `node_modules/`, build artifacts, etc.) are excluded from astwire's output by default, without additional configuration.
**This now holds for `-i`/`--resolve-imports` too.** Per SPEC-1.0.md ยง5 ("Skip/ignore win over `-i`"), `expand_local_imports()` (`discover.py`) checks every resolved import target against the same `IgnoreEngine` and `targeting.skip` patterns used for plain target walks (`is_excluded(..., for_import=True)`), in addition to its own hard-deny on vendor-style dirnames (`node_modules/`, `vendor/`, `.venv/`, etc.). A file reachable only through an import is *not* bundled if `.gitignore`/`.astwireignore`/`skip` would have excluded it โ skip/ignore rules win over the import graph, not the other way around.
## 4. Git Subprocess Calls (`--since`)
`--since` (`git_changes.py`) shells out to the system `git` binary (`subprocess.run`) to resolve the repository root, verify the given ref, and list changed/untracked files โ it does not use a bundled git implementation or make any network call itself. All of this stays local: `git diff`/`git ls-files` read the local working tree and object database only. As with the rest of astwire, no network request is made by this path unless your local `git` config itself is set up to do so (e.g. a ref that requires a prior `fetch` to exist โ astwire never runs `fetch` or contacts a remote).
This module is deliberately narrow and does not call any AI/LLM API, does not cache results or write markers between runs (every invocation re-derives its answer from `git`), and never resolves a remote or base branch on your behalf โ `REF` is always exactly what you passed on the command line. Unlike the rest of astwire's pipeline, `--since`'s own seed list *is* gitignore-aware (it explicitly excludes paths `git` itself reports as ignored) โ consistent with the rest of the pipeline now that `-i` import-expansion is gitignore-aware too (Section 3).
## 5. Configuration File Trust
`.astwire.toml` is discovered by walking upward from the resolution root (see [`astwire-architecture.md`](astwire-architecture.md)) and parsed with `tomllib`/`tomli`. It is a plain data file โ it cannot contain executable code, and a malformed or unreadable config file causes `load_config()` to silently fall back to defaults rather than raising.
## 6. Uninstallation Data Handling
`astwire --uninstall` removes the installed binary and local configuration files it created: `.astwire.toml` and `.astwireignore` in the current directory, plus `.astwire.toml` under `$HOME` (`perform_uninstall()` does not currently remove a `$HOME/.astwireignore`, since astwire itself never writes one there). No data is transmitted anywhere as part of uninstallation. On Windows, the uninstall step is scheduled as a detached PowerShell process (since the running binary cannot delete its own locked executable file); this is a local process-spawn, not a network operation.
## 7. Security Recommendations
1. Review generated `context.md` / `.xml` / `.json` output before pasting it into a hosted LLM, especially for proprietary or regulated code.
2. Don't rely on `redact_secrets()` as your only line of defense โ combine it with `.gitignore`/`.astwireignore` exclusions for files that should never be read in the first place.
3. Prefer `--skeleton` mode when you only need interface shape (signatures, types, docstrings) rather than full implementation bodies โ it inherently reduces the amount of code content, including any secrets embedded in function bodies, that reaches the output.
4. `-i`/`--resolve-imports` respects `.gitignore`/`.astwireignore`/`skip` the same way plain target resolution does โ skip/ignore rules win over the import graph. If you need a file excluded from import-graph traversal specifically, add it to `.astwireignore` or `targeting.skip` in `.astwire.toml`.
5. Treat the `installers/` binaries and `.astwire.toml` the same way you'd treat any other local build artifact or config file with respect to your organization's source-control and secret-scanning policies.