feat: add agent-os bootstrap bundle

This commit is contained in:
2026-07-02 14:48:49 +00:00
parent d0a9a267fd
commit 5f9302abc5
20 changed files with 715 additions and 0 deletions
+6
View File
@@ -1,8 +1,14 @@
# Runtime output is generated on the server and must not become source history. # Runtime output is generated on the server and must not become source history.
logs/ logs/
# Bootstrap exports are generated bundles. Source lives in bootstrap/templates/.
bootstrap/exports/
# Claude Code compatibility memory is generated/symlinked runtime state. # Claude Code compatibility memory is generated/symlinked runtime state.
claude-code/ claude-code/
# Operational tools are deployed from the nxm-stacks repository. # Operational tools are deployed from the nxm-stacks repository.
tools/ tools/
# Python cache generated by local validation.
__pycache__/
*.pyc
+32
View File
@@ -0,0 +1,32 @@
# Agent OS Bootstrap
This directory owns the source for the generic Agent OS bootstrap bundle.
The Linux Server design docs are the source specification:
- `/home/nxm/Documents/NxM Linux Server/Services/Agents.md` defines the Agent OS foundation, the `/opt/agent-os` runtime root, and the agent output contract.
- `/home/nxm/Documents/NxM Linux Server/Operations/Git Workflow.md` defines the Gitea source-of-truth flow and says generated runtime state must stay out of commits.
- `/home/nxm/Documents/NxM Linux Server/Current Work.md` records the clone synchronization baseline for Agent OS.
## Files
- `bundle-manifest.json` lists the canonical files and directories in the generic bundle.
- `export-rules.json` defines which metadata is exported and which paths must verify.
- `templates/generic/` holds the canonical bootstrap templates.
- `generate-export.py` creates `bootstrap/exports/generic` from the manifest and rules.
## Generate
From a checked-out Agent OS clone:
```bash
python3 bootstrap/generate-export.py
```
To generate the live runtime export requested by the server workflow:
```bash
sudo -n python3 bootstrap/generate-export.py --output /opt/agent-os/bootstrap/exports/generic
```
Generated exports are intentionally ignored by Git.
+138
View File
@@ -0,0 +1,138 @@
{
"schema_version": 1,
"bundle": {
"id": "agent-os-generic-bootstrap",
"name": "Agent OS Generic Bootstrap",
"version": "2026.07.02",
"description": "Canonical starter bundle for a plain-files Agent OS runtime.",
"runtime_root": "/opt/agent-os",
"export_id": "generic",
"export_root": "bootstrap/exports/generic"
},
"source_spec": [
{
"path": "/home/nxm/Documents/NxM Linux Server/Services/Agents.md",
"sections": [
"Agent Output Convention",
"Static Utility Pages",
"Agent OS Foundation"
]
},
{
"path": "/home/nxm/Documents/NxM Linux Server/Operations/Git Workflow.md",
"sections": [
"Source-to-Deployment Flow",
"Repository Layout",
"Files That Must Not Be Committed",
"Minimum Ignore Pattern"
]
},
{
"path": "/home/nxm/Documents/NxM Linux Server/Current Work.md",
"sections": [
"Current Baseline",
"Automated Continuity Controls"
]
}
],
"directories": [
{
"path": "context",
"keep": true
},
{
"path": "logs",
"keep": true,
"runtime_generated": true
},
{
"path": "memory",
"keep": false
},
{
"path": "skills",
"keep": false
},
{
"path": "skills/_template/context",
"keep": true
}
],
"templates": [
{
"source": ".gitignore",
"target": ".gitignore",
"mode": "0644"
},
{
"source": "README.md",
"target": "README.md",
"mode": "0644"
},
{
"source": "CLAUDE.md",
"target": "CLAUDE.md",
"mode": "0644"
},
{
"source": "identity.md",
"target": "identity.md",
"mode": "0644"
},
{
"source": "brain.md",
"target": "brain.md",
"mode": "0644"
},
{
"source": "context/.gitkeep",
"target": "context/.gitkeep",
"mode": "0644"
},
{
"source": "memory/active-projects.md",
"target": "memory/active-projects.md",
"mode": "0644"
},
{
"source": "memory/constraints.md",
"target": "memory/constraints.md",
"mode": "0644"
},
{
"source": "memory/notes-from-last-run.md",
"target": "memory/notes-from-last-run.md",
"mode": "0644"
},
{
"source": "memory/persistent.md",
"target": "memory/persistent.md",
"mode": "0644"
},
{
"source": "memory/recent-decisions.md",
"target": "memory/recent-decisions.md",
"mode": "0644"
},
{
"source": "skills/_template/skill.md",
"target": "skills/_template/skill.md",
"mode": "0644"
},
{
"source": "skills/_template/learnings.md",
"target": "skills/_template/learnings.md",
"mode": "0644"
},
{
"source": "skills/_template/eval.json",
"target": "skills/_template/eval.json",
"mode": "0644"
},
{
"source": "skills/_template/context/handoff.md",
"target": "skills/_template/context/handoff.md",
"mode": "0644"
}
]
}
+108
View File
@@ -0,0 +1,108 @@
{
"schema_version": 1,
"export_id": "generic",
"description": "Build a self-contained generic bootstrap bundle from canonical templates.",
"metadata": [
{
"source": "bundle-manifest.json",
"target": "bundle-manifest.json",
"mode": "0644"
},
{
"source": "export-rules.json",
"target": "export-rules.json",
"mode": "0644"
}
],
"template_root": "templates/generic",
"ignored_source_paths": [
"exports/",
"__pycache__/",
".DS_Store"
],
"verify": {
"required": [
{
"path": "bundle-manifest.json",
"type": "file"
},
{
"path": "export-rules.json",
"type": "file"
},
{
"path": ".gitignore",
"type": "file"
},
{
"path": "README.md",
"type": "file"
},
{
"path": "CLAUDE.md",
"type": "file"
},
{
"path": "identity.md",
"type": "file"
},
{
"path": "brain.md",
"type": "file"
},
{
"path": "context",
"type": "directory"
},
{
"path": "logs",
"type": "directory"
},
{
"path": "memory/active-projects.md",
"type": "file"
},
{
"path": "memory/constraints.md",
"type": "file"
},
{
"path": "memory/notes-from-last-run.md",
"type": "file"
},
{
"path": "memory/persistent.md",
"type": "file"
},
{
"path": "memory/recent-decisions.md",
"type": "file"
},
{
"path": "skills/_template/skill.md",
"type": "file"
},
{
"path": "skills/_template/learnings.md",
"type": "file"
},
{
"path": "skills/_template/eval.json",
"type": "file"
},
{
"path": "skills/_template/context/handoff.md",
"type": "file"
}
],
"forbidden": [
".env",
".env.*",
"*.pem",
"*.key",
"*.sqlite",
"*.sqlite3",
"*.db"
]
}
}
+147
View File
@@ -0,0 +1,147 @@
#!/usr/bin/env python3
"""Generate and verify Agent OS bootstrap exports."""
from __future__ import annotations
import argparse
import fnmatch
import json
import shutil
import stat
import sys
from pathlib import Path
BOOTSTRAP_ROOT = Path(__file__).resolve().parent
DEFAULT_OUTPUT = BOOTSTRAP_ROOT / "exports" / "generic"
def load_json(path: Path) -> dict:
with path.open("r", encoding="utf-8") as handle:
return json.load(handle)
def parse_mode(mode: str) -> int:
return int(mode, 8)
def ensure_safe_output(output: Path) -> Path:
resolved = output.resolve()
if resolved.parts[-3:] != ("bootstrap", "exports", "generic"):
raise SystemExit(
"refusing to write outside a bootstrap/exports/generic directory: "
f"{resolved}"
)
return resolved
def copy_file(source: Path, target: Path, mode: str) -> None:
if not source.is_file():
raise FileNotFoundError(f"missing source file: {source}")
target.parent.mkdir(parents=True, exist_ok=True)
shutil.copyfile(source, target)
target.chmod(parse_mode(mode))
def clean_output(output: Path) -> None:
ensure_safe_output(output)
if output.exists():
shutil.rmtree(output)
output.mkdir(parents=True, exist_ok=True)
def create_directories(output: Path, manifest: dict) -> None:
for directory in manifest["directories"]:
target = output / directory["path"]
target.mkdir(parents=True, exist_ok=True)
if directory.get("keep"):
keep_file = target / ".gitkeep"
keep_file.touch()
keep_file.chmod(stat.S_IRUSR | stat.S_IWUSR | stat.S_IRGRP | stat.S_IROTH)
def export_bundle(output: Path, manifest: dict, rules: dict) -> None:
clean_output(output)
create_directories(output, manifest)
for item in rules["metadata"]:
copy_file(
BOOTSTRAP_ROOT / item["source"],
output / item["target"],
item.get("mode", "0644"),
)
template_root = BOOTSTRAP_ROOT / rules["template_root"]
for item in manifest["templates"]:
copy_file(
template_root / item["source"],
output / item["target"],
item.get("mode", "0644"),
)
def verify_required(output: Path, rules: dict) -> list[str]:
failures: list[str] = []
for item in rules["verify"]["required"]:
target = output / item["path"]
expected_type = item["type"]
if expected_type == "file" and not target.is_file():
failures.append(f"missing file: {item['path']}")
elif expected_type == "directory" and not target.is_dir():
failures.append(f"missing directory: {item['path']}")
return failures
def verify_forbidden(output: Path, rules: dict) -> list[str]:
failures: list[str] = []
for path in output.rglob("*"):
rel = path.relative_to(output).as_posix()
for pattern in rules["verify"].get("forbidden", []):
if fnmatch.fnmatch(rel, pattern):
failures.append(f"forbidden path exported: {rel}")
return failures
def verify_export(output: Path, rules: dict) -> None:
failures = verify_required(output, rules) + verify_forbidden(output, rules)
if failures:
for failure in failures:
print(f"FAIL {failure}", file=sys.stderr)
raise SystemExit(1)
def count_files(output: Path) -> int:
return sum(1 for path in output.rglob("*") if path.is_file())
def main() -> int:
parser = argparse.ArgumentParser(description=__doc__)
parser.add_argument(
"--output",
type=Path,
default=DEFAULT_OUTPUT,
help="Export directory. Must end in bootstrap/exports/generic.",
)
parser.add_argument(
"--verify-only",
action="store_true",
help="Verify an existing export without regenerating it.",
)
args = parser.parse_args()
output = ensure_safe_output(args.output)
manifest = load_json(BOOTSTRAP_ROOT / "bundle-manifest.json")
rules = load_json(BOOTSTRAP_ROOT / "export-rules.json")
if not args.verify_only:
export_bundle(output, manifest, rules)
verify_export(output, rules)
print(f"OK {manifest['bundle']['id']} -> {output}")
print(f"OK verified {len(rules['verify']['required'])} required paths")
print(f"OK exported {count_files(output)} files")
return 0
if __name__ == "__main__":
raise SystemExit(main())
+23
View File
@@ -0,0 +1,23 @@
# Runtime output is generated on the server and must not become source history.
logs/
# Bootstrap exports are generated bundles. Source lives in bootstrap/templates/.
bootstrap/exports/
# Claude Code compatibility memory is generated/symlinked runtime state.
claude-code/
# Local secrets and deployment state must never be committed.
.env
.env.*
!.env.example
*.log
__pycache__/
*.pyc
.cache/
data/
uploads/
backups/
*.db
*.sqlite
*.sqlite3
+36
View File
@@ -0,0 +1,36 @@
# Agent OS Project Brief
## What This Project Is
Agent OS is a tool-agnostic, plain-files operating layer for LLM agents. Markdown files are the shared memory, operating contract, and handoff surface.
## Runtime
- Server runtime root: `/opt/agent-os/`
- Scheduled jobs: local scheduler or cron on the server
- Agent web output: `/opt/sites/<short-name>/`
- Agent status logs: `/opt/agent-os/logs/<agent>/last-run.json`
## Required Output Contract
Every scheduled or autonomous agent should write:
- `last-run.json` at `/opt/agent-os/logs/<agent>/last-run.json`
- `last-output.md` at `/opt/sites/<short-name>/last-output.md`
Keep `last-output.md` concise: heading, timestamp, and useful summary.
## Repository Rules
- Gitea or the configured remote is the recoverable source of truth.
- Runtime state, logs, caches, credentials, databases, uploads, and generated exports stay out of commits.
- Review and validate changes before deployment.
- Copy successful live fixes back to the edit clone before committing.
## First-Run Checklist
1. Fill in `identity.md`.
2. Fill in stable infrastructure facts in `brain.md`.
3. Record non-negotiable constraints in `memory/constraints.md`.
4. Replace this project brief with environment-specific status.
5. Add real skills under `skills/<skill-name>/`.
+31
View File
@@ -0,0 +1,31 @@
# Agent OS
A plain-files operating layer for agents and LLM tools.
## First Read
1. Read `identity.md` for owner preferences, hard limits, and communication style.
2. Read `brain.md` for stable infrastructure and project facts.
3. Read `memory/active-projects.md` for current work.
4. Read `memory/constraints.md` for non-negotiable safety rules.
5. Read `CLAUDE.md` for runtime conventions and project status.
## Runtime Contract
- Runtime root: `/opt/agent-os/`
- Machine-readable agent status: `/opt/agent-os/logs/<agent>/last-run.json`
- Human-readable agent output: `/opt/sites/<short-name>/last-output.md`
- Credentials: reference the approved secret store only; do not write secret values into this repo.
## Directory Layout
| Path | Purpose |
|---|---|
| `identity.md` | Owner profile, communication preferences, hard limits |
| `brain.md` | Stable facts, services, hosts, ports, standing decisions |
| `memory/` | Persistent and recent working memory |
| `context/` | Dated task-specific working notes |
| `skills/` | Repeatable workflows and skill learnings |
| `logs/` | Generated runtime status output, ignored by Git |
This bundle is generic. Replace placeholders before trusting an agent to act.
+37
View File
@@ -0,0 +1,37 @@
# Brain
Stable facts that every agent may need.
## Infrastructure
| Name | Address | Purpose | Notes |
|---|---|---|---|
| | | | |
## Services
| Service | URL | Port | Owner | Notes |
|---|---|---|---|---|
| | | | | |
## Agents
| Short Name | Full Name | Role | Status | Output |
|---|---|---|---|---|
| | | | | |
## Repositories
| Repository | Remote | Runtime Path | Notes |
|---|---|---|---|
| | | | |
## Standing Decisions
- Keep generated runtime output out of Git.
- Keep credentials in the approved secret store only.
- Prefer reviewed edit-clone changes over live-only edits.
## Open Questions
-
+29
View File
@@ -0,0 +1,29 @@
# Identity
## Owner
- Name:
- Organization:
- Role:
- Primary timezone:
- Preferred working hours:
## Communication Preferences
- Preferred tone:
- Detail level:
- Escalation style:
- Decision-making preferences:
## Hard Limits
- Do not expose credentials, private keys, or customer data.
- Do not perform destructive or high-impact actions without explicit approval.
- Do not restart or redeploy production services unless the requested change requires it and validation is ready.
## Useful Context
- Important people:
- Important systems:
- Standing priorities:
- Things to avoid:
@@ -0,0 +1,7 @@
# Active Projects
Update this file when work starts, pauses, completes, or changes owner.
| Project | Status | Owner | Next Action |
|---|---|---|---|
| | | | |
@@ -0,0 +1,19 @@
# Constraints
Rules in this file override convenience.
## Security
- Never write credential values into code, logs, docs, generated reports, or chat output.
- Use placeholder examples for configuration shape.
- Treat customer data and private infrastructure details as sensitive.
## Operations
- Confirm target path, branch, remote, and worktree status before deployment.
- Keep live fixes synchronized back to the edit clone.
- Validate syntax and intended behavior before service reloads or restarts.
## Environment-Specific Limits
-
@@ -0,0 +1,7 @@
# Notes From Last Run
Clear or roll up this file at the start of each new session.
## Notes
-
@@ -0,0 +1,19 @@
# Persistent Memory
Facts that are expected to remain true for a long time.
## People
-
## Systems
-
## Preferences
-
## Lessons
-
@@ -0,0 +1,7 @@
# Recent Decisions
Record decisions from the last 30 days or the current work cycle.
| Date | Decision | Reason | Follow-Up |
|---|---|---|---|
| | | | |
@@ -0,0 +1,21 @@
# Handoff
## Objective
-
## Completed
-
## Validation
-
## Risks
-
## Next Action
-
@@ -0,0 +1,17 @@
{
"schema_version": 1,
"criteria": [
{
"name": "correctness",
"description": "The skill produces the requested result without inventing facts."
},
{
"name": "safety",
"description": "The skill respects credentials, approvals, and operational limits."
},
{
"name": "handoff_quality",
"description": "The skill writes clear output and next steps for humans or other agents."
}
]
}
@@ -0,0 +1,5 @@
# Learnings
Append stable lessons from real runs. Keep this concise and actionable.
-
@@ -0,0 +1,26 @@
# Skill Name
## Purpose
Describe what this skill does and when an agent should use it.
## Inputs
-
## Workflow
1. Read the relevant context.
2. Perform the smallest safe action that satisfies the request.
3. Write outputs to the documented runtime paths.
4. Record useful learnings in `learnings.md`.
## Outputs
- `/opt/agent-os/logs/<agent>/last-run.json`
- `/opt/sites/<short-name>/last-output.md`
## Safety
- Do not expose secrets.
- Ask for approval before destructive or high-impact actions.