- DOX is highly performant AGENTS.md hierarchy installed here
- Agent must follow DOX instructions across any edits
## Core Contract
- AGENTS.md files are binding work contracts for their subtrees
- Work products, source materials, instructions, records, assets, and durable docs must stay understandable from the nearest applicable AGENTS.md plus every parent AGENTS.md above it
## Read Before Editing
1. Read the root AGENTS.md
2. Identify every file or folder you expect to touch
3. Walk from the repository root to each target path
4. Read every AGENTS.md found along each route
5. If a parent AGENTS.md lists a child AGENTS.md whose scope contains the path, read that child and continue from there
6. Use the nearest AGENTS.md as the local contract and parent docs for repo-wide rules
7. If docs conflict, the closer doc controls local work details, but no child doc may weaken DOX
Do not rely on memory. Re-read the applicable DOX chain in the current session before editing.
## Update After Editing
Every meaningful change requires a DOX pass before the task is done.
Update the closest owning AGENTS.md when a change affects:
- purpose, scope, ownership, or responsibilities
- durable structure, contracts, workflows, or operating rules
- required inputs, outputs, permissions, constraints, side effects, or artifacts
- user preferences about behavior, communication, process, organization, or quality
- AGENTS.md creation, deletion, move, rename, or index contents
Update parent docs when parent-level structure, ownership, workflow, or child index changes. Update child docs when parent changes alter local rules. Remove stale or contradictory text immediately. Small edits that do not change behavior or contracts may leave docs unchanged, but the DOX pass still must happen.
## Hierarchy
- Root AGENTS.md is the DOX rail: project-wide instructions, global preferences, durable workflow rules, and the top-level Child DOX Index
- Child AGENTS.md files own domain-specific instructions and their own Child DOX Index
- Each parent explains what its direct children cover and what stays owned by the parent
- The closer a doc is to the work, the more specific and practical it must be
## Child Doc Shape
- Create a child AGENTS.md when a folder becomes a durable boundary with its own purpose, rules, responsibilities, workflow, materials, or quality standards
- Work Guidance must reflect the current standards of the project or user instructions; if there are no specific standards or instructions yet, leave it empty
- Verification must reflect an existing check; if no verification framework exists yet, leave it empty and update it when one exists
Default section order:
- Purpose
- Ownership
- Local Contracts
- Work Guidance
- Verification
- Child DOX Index
## Style
- Keep docs concise, current, and operational
- Document stable contracts, not diary entries
- Put broad rules in parent docs and concrete details in child docs
- Prefer direct bullets with explicit names
- Do not duplicate rules across many files unless each scope needs a local version
- Delete stale notes instead of explaining history
- Trim obvious statements, repeated rules, misplaced detail, and warnings for risks that no longer exist
## Closeout
1. Re-check changed paths against the DOX chain
2. Update nearest owning docs and any affected parents or children
3. Refresh every affected Child DOX Index
4. Remove stale or contradictory text
5. Run existing verification when relevant
6. Report any docs intentionally left unchanged and why
## User Preferences
When the user requests a durable behavior change, record it here or in the relevant child AGENTS.md
## Child DOX Index
This project is not yet indexed. Before continuing you must scan the project, build the DOX tree and replace this message with the actual index. Go deep and scan files recursively to properly evaluate complexity and create nested DOX files where needed.
# AGENTS.md
Agent handbook for the ShellSpy (Punk Shell) repository. These guidelines cover builds, linting, testing, code style, and day-to-day conventions for all contributors and agentic assistants. Always check for nested `AGENTS.md` files before editing subdirectories—this root spec applies repo-wide unless overridden deeper in the tree.
Agent handbook for the ShellSpy (Punk Shell) repository. These guidelines cover builds, linting, testing, code style, and day-to-day conventions for all contributors and agentic assistants. Always check for nested `AGENTS.md` files before editing subdirectories. This root spec applies repo-wide unless overridden deeper in the tree.
- Run `tclsh make.tcl` once after cloning to populate generated assets.
- Run `tclsh src/make.tcl packages` once after cloning to populate generated assets.
- Keep edits within the scoped instructions of any nested `AGENTS.md`.
- Use `tclint` before submitting code to align formatting and structure.
- Execute at least one relevant test script (`tclsh scriptlib/tests/<file>.tcl`).
- Use `tclint` before submitting code to align formatting and structure for any new agent-produced code, but do not use it to reformat existing code.
- Execute at least one relevant test script (`tclsh src/tests/<path>/<file>.tcl`).
- Document changes impacting build, tooling, or developer workflow.
## Build & Bootstrap Commands
- **Primary build**: `tclsh make.tcl` (Windows default) or `punk make.tcl` inside Punk shell.
- **Alt entry point**: `punk build.tcl` or `tclsh build.tcl` for kettle-style builds.
- **Bootstrap shell**: `pmix KettleShell` from inside Punk shell for advanced packaging tasks.
- **Clean/resync**: Remove `build/` artifacts then rerun `tclsh make.tcl`; avoid partial cleans that break boot modules.
- **Binary images**: Use `punk make.tcl --target <name>` when producing platform-specific bundles (see script comments for targets).
- **Primary build**: `tclsh make.tcl project` (Windows default) or `punk902z make.tcl project` inside Punk shell.
- **Clean/resync**: Remove `_build/` artifacts then rerun `tclsh make.tcl project`; avoid partial cleans that break boot modules. Cleaning _build is generally not required.
- **Binary images**: Use `punk make.tcl project` to produce punk binaries. There are no platform-specific flags for cross-platform building - it must currently be done on each specific platform. The Tcl modules and libs are mostly cross-platform by nature, but the built binaries rely on platform specific runtimes and some binary packages from whichever src/vfs/*.vfs folder was used to build.
## Testing Strategy
- **Test location**: `scriptlib/tests/` holds all Tcl test scripts; keep new tests there.
- **Run entire suite**: Iterate with `for /r scriptlib\tests %f in (*.tcl) do tclsh %f` (Windows) or a similar shell loop on POSIX.
- **Run single test**: `tclsh scriptlib/tests/<test_name>.tcl` (e.g., `tclsh scriptlib/tests/json.tcl`).
- **Test location**: `src/tests/` holds all Tcl test scripts; keep new tests there, named with the .test file extension.
- **Run entire suite**: Run base src/tests/runtests.tcl or Iterate with something like `for /r src\tests %f in (*.tcl) do tclsh %f` (Windows) or a similar shell loop on POSIX.
- **Run single test**: `tclsh src/tests/<path>/<script>.tcl` (e.g., `tclsh src/tests/modules/opunk/str/tests/all.tcl`).
- **Focused verification**: Mirror production pipelines inside tests using Punk pipeline syntax for parity.
- **Test dependencies**: Every test must `package require punk`; declare extra packages explicitly to avoid hidden dependencies.
- **Command**: `tclint` (configured via `tclint.toml` in repo root).
- **Files covered**: `.tcl`, `.tm`, `.sdc`; extend config if new extensions appear.
- **Command**: N/A - tclint is currently only available as a plugin in vscode (configured via `tclint.toml` in repo root).
- **Files covered**: `.tcl`, `.tm` extend config if new extensions appear.
- **Line length**: Hard cap at 400 characters; wrap pipelines thoughtfully instead of exceeding.
- **Blank lines**: No more than 10 consecutive blanks.
- **Indentation**: 4 spaces; tabs are disallowed in Tcl sources except inside string literals.
- **Auto-fixes**: Run `tclint --fix` only when you have reviewed the resulting diff.
## Toolchain & Dependencies
- Prefer the provided vendor modules under `src/vendor*` before fetching new dependencies.
- Use `tcl::tm::path add <dir>` to surface project modules when writing new tooling.
- Keep compatibility with Tcl 8.6+; gate 9.0-specific features behind version checks.
- Keep compatibility with Tcl 8.6+; gate 9.0-specific features behind version checks, or use existing punk::lib::compat functions.
- When optional compiled extensions (e.g., `twapi`, `tdom`) are necessary, guard `package require` calls with fallback messaging.
## Repository Layout Primer
```
modules/ # Target module folder for when `tclsh src/make.tcl modules` is run. Agents should not directly modify.
lib/ # Target library folder for when `tclsh src/make.tcl libs` is run. Agents should not directly modify.
src/
bootsupport/modules/ # Early-load modules with minimal deps
modules/ # Main Punk modules (.tm)
lib/ # Classic Tcl libraries
bootsupport/modules/ # Early-load modules with minimal deps. These are analogous to npm devDependencies. Agents should not directly modify.
modules/ # Main Punk modules (.tm) - most development for punkshell is in this section.
modules/test # Hierarchy for unit tests that have been bundled into .tm module-based test packages with module name portion beginning with 'test' namespace/folder matching the namespace/folder of the module to be tested. Agents should generally not update this area aside from updating versions as necessary in <modulename>-buildversion.txt files, as it is generated from src/tests or manually updated by the user. Running these tests, tests the installed module/library state (that acheived after running `tclsh src/make.tcl packages|modules|lib`)
lib_tcl8/ # Tcl8 specific pgkIndex.tcl-based libraries
lib_tcl9/ # Tcl9 specific pgkIndex.tcl-based libraries
runtime/ # Location of mapvfs.config which determines which src/vfs/*.vfs folders are mapped with which runtime executable.
scriptapps/ # Entry-point scripts for Punk apps
vendormodules*/ # Third-party modules bundled with repo
scriptlib/ # Shared utilities + tests
bin/ # Helper binaries/scripts
callbacks/, plugj.tcl, etc # Integration glue for host environments
src/vfs/* # Virtual file system images for builds
testansi/ # sample files for punk::ansi features. Agents should not modify.
vendormodules/ # Third-party modules bundled with repo. .tm files are either manually placed here or refreshed based on include_modules.config using `tclsh src/make.tcl vendorupdate`.
tests/ # Unit tests (using the tcltest package) - these are designed to run against the modules in the src hierarchy. ie prior to installation.
vfs/ # Virtual file system images for builds - *.vfs folders are currently manually updated by the user, not Agent modified.
vfs/_config/ # Entry point .tcl files for executables built from the *.vfs folders.
vfs/_vfscommon.vfs # Common libraries to be integrated into vfs during executable building. These are completley refreshed by running `tclsh src/make.tcl vfscommonupdate` - not modified directly by user or agents.
scriptlib/ # Shared utilities + manual tests. Updated by user only unless explicit request made for agent to modify.
bin/ # Helper binaries/scripts. Target for built punk binaries made from bin/runtime/<platform>/*.exe files and associated src/vfs/*.vfs folders. Agents should not modify.
bin/runtime/* # Immediate subfolders are named for the target platform. These are where specific pre-built runtimes are installed by the bin/runtime.cmd helper script (or manually). Agents should not modify.
callbacks/ # Experimental features for when punkshell is launched with the "shellspy" parameter. Agents should not modify.
```
Treat VFS directories as generated artifacts; edit them only when updating runtime payloads.
## File Resolution Policy
Use the strongest available anchor first and do not broaden scope until that anchor is checked.
### Anchor Order
1. Exact path named by the user.
2. Active editor file, when the environment provides one.
3. Exact proc, symbol, or identifier named by the user.
4. Repository naming and source-precedence rules.
Do not skip a stronger anchor for a weaker one.
### Source Priority
- For editable Punk module source, prefer `src/modules/`.
- Source module filenames use the literal suffix `-999999.0a1.0.tm`.
- Do not shorten or normalize that suffix.
- For editable Tcl library source, prefer `src/lib/`.
- Treat `src/modules_tcl<major>/` and `src/lib_tcl<major>/` as Tcl-major-version-specific source trees.
- Prefer generic source in `src/modules/` or `src/lib/` unless the package, proc, or surrounding package mapping is specific to a Tcl major version or exists only in a version-specific tree.
- Treat `pkgIndex.tcl` as a loader map unless the task is about package loading or registration.
- If the best hit is `pkgIndex.tcl`, resolve the implementation file and continue there.
- Prefer editable source over bootstrap, VFS, built, installed, project layout, or generated copies unless the user explicitly targets one of those.
### Proc Inspection Order
1. Read the exact file named by the user, if provided.
2. Otherwise read the active editor file, if provided and relevant.
3. Otherwise search once for the exact proc name.
4. Prefer editable source under `src/modules/`, `src/modules_tcl<major>/`, `src/lib/`, or `src/lib_tcl<major>/`.
5. If multiple matches exist, prefer the generic source tree unless version-specific behavior is relevant or only a version-specific definition exists.
6. If the best hit is `pkgIndex.tcl`, use it to resolve the implementation file.
7. Once the owning source file is identified, continue locally from that file.
### Recovery After Wrong Path Guess
- Re-check user-provided path.
- Re-check active editor file, if available.
- Re-check repo naming conventions.
- Use one exact symbol search instead of probing more filename variants.
## Imports & Package Management
- Always declare dependencies explicitly using `package require <name>` near file tops.
- Organize custom modules as `namespace eval punk::<segment>` with filenames like `src/modules/punk/<segment>-<version>.tm`.
- Organize custom modules as `namespace eval punk::<modulename>` with filenames like `src/modules/punk/<modulename>-<magicversionnumber>.tm`.
- Custom modules can have deeper hierarchies such as `punk::lib::util::<somename>` with a corresponding directory structure.
- Use semantic versions that `package vcompare` can interpret; strip leading zeros.
- For optional features, probe with `if {[catch {package require foo}]} { ... }` and degrade gracefully.
## Formatting & Layout Rules
- Opening braces stay on the same line for procs; multiline control structures may place braces on new lines for readability.
- Align continuations under their opening command; use explicit `\` when mapping to pipeline syntax is unclear.
- Opening braces stay on the same line for procs; multiline control structures may span lines for readability if Tcl syntax allows without using line-continuation-backslash. e.g braced `expr` contents (or `if` expressions)
- Line continuation backslashes should only be used in documentation blocks for use with punk::args (ie in 'punk::args::define' arguments or in 'lappend PUNKARGS' elements)
- proc contents should not use line continuation backslashes as it can make debug line-number matching harder. use Tcl expand operator with an opening brace instead.
e.g
dict create {*}{
a A
b B
c C
}
This works in a single block for literals, but for values that need substitution, additional expand with brace pairs may be needed.
e.g
dict create {*}{
} a A
b B
c C {*}{
} d $DVAL {*}{
}
- Keep pipelines readable by aligning `% var = ...` and `pipecase` segments vertically when possible.
- Document non-trivial procedures and exports with the standard header template (see below).
@ -74,17 +231,63 @@ Treat VFS directories as generated artifacts; edit them only when updating runti
- **Private helpers**: Prefix with `_` (e.g., `_resolve_stream`); do not export them.
- **Constants**: `UPPER_CASE_WITH_UNDERSCORES` declared via `namespace eval { variable CONSTANT value }` when practical.
## Procedure Documentation Template
## Procedure Documentation Template Guide
```tcl
# <Proceduresummary>
# Args:
# arg1 - description
# arg2 - description
# Returns:
# Description of return value
proc procedure_name {arg1 arg2} {
# Implementation
}
#- comments such as this with a leading dash are descriptions for the agent of how-to/what-to to implement
#- whereas comments without the dash are either literal comments, or if angle-bracketed, descriptions of what to put in the comment.
#- If performance sensitive or not part of a broad-concept of 'API' for the module and useful utilities,
#- use fast `switch` based code to parse the arguments.
#- procedure functionality implementation
}
```
Update the template with concrete details whenever functions are user-facing or complex.
@ -101,6 +304,7 @@ Update the template with concrete details whenever functions are user-facing or
- Never swallow errors silently; propagate with context so shell users see actionable details.
## Pipeline & Functional Style Notes
- Punk Pipeline functionality is somewhat experimental/in-flux and should usually be avoided for AI generated code unless the user specifically requests it.
- Use `% var = ...` bindings to capture intermediate values; keep names meaningful.
- `pipecase` should list specific patterns before catch-alls to avoid hidden matches.
- `fun name pattern { ... }` definitions should remain side-effect light; treat them as pure functions unless otherwise documented.
@ -108,32 +312,100 @@ Update the template with concrete details whenever functions are user-facing or
## Module Structure Expectations
```tcl
# Module description
# <Moduledescription>
package require <dependencies>
#- comments such as this with a leading dash are descriptions for the agent of how-to/what-to to implement
#- whereas comments without the dash are either literal comments, or if angle-bracketed, descriptions of what to put in the comment.
namespace eval <module_namespace> {
variable version <semver>
namespace export public_proc1 public_proc2
namespace eval argdoc {
lappend PUNKARGS [list {
@id -id <module_namespace>::public_proc1
... elided ...
#- punk::args textblock similar to example given in Procedure Documentation Template
#- This should exist immediately prior to each proc (or at least very close),
#- even if it is only being used for documentation and not for parsing.
#- If the public_proc1 proc does not use the PUNKARGS definition for parsing; then the parsing within the proc
#- and the punk::args definitions of proc args and behaviour; must be kept synchronized.
}]
}
proc public_proc1 {args} {
# Implementation
#- argument parsing code, using `punk::args::parse` if part of API and not performance critical
#- if argument parsing is done in code here - the behaviour must match the arguments as defined in the PUNKARGS list created above.
package provide <module_namespace> [tcl::namespace::eval <module_namespace> {
variable version
#- this version number, exactly 999999.0a1.0 is a literal that should be used in all src/module folders
#- we refer to this sometimes as the 'magic version number'
set version 999999.0a1.0
}]
return
```
Ensure module filenames include the version (`punk/console-0.1.1.tm`), and keep `namespace export` lists alphabetized for clarity.
Ensure module filenames include the magic version (`punk/<subpath>/<modulename>-999999.0a1.tm`), and keep `namespace export` lists alphabetized for clarity.
## Type & Data Handling
- Tcl is dynamically typed; emulate structural typing via argument validation at proc boundaries.
- Validate user inputs with `switch -exact`, `regexp`, or Punk pipeline predicates before mutation.
- Use dictionaries for structured data; avoid parallel lists.
- Validate user inputs with punk::args::parse or `switch -exact`, `regexp`, or Punk pipeline predicates before mutation.
- Use dictionaries for structured data, or parallel lists if it is likely to be a performance win.
- Tcl arrays can also be used, but limit to simple flat structures, or cases where it is specifically warranted.
- When bridging to binary data (e.g., ANSI/xbin parsing), document expected encodings and conversions.
## Versioning & Releases
- Stick to semantic versioning (`major.minor.patch`).
- Use the magic version 999999.0a1.0 for src/modules src/modules_tcl9 etc and add/update the actual version number in the associated <modulename>-buildversion.txt file.
- Update the <modulename>-buildversion.txt file when API changes are made
- There may be occasional exceptions such as punk::libunknown-0.1.tm which is deliberately manually versioned, but new modules should use the magic version mechanism.
- vendormodules and modules in .vfs folders or src/bootsupport/modules should not use the magic version mechanism, nor should modules with the magic version number appear in the output paths such as <projectdir>/modules
- When referencing ranges, use bounded specs (e.g., `1.2.3-2.0.0`).
- Convert loose versions to bounded form in module metadata; helper utilities exist in boot modules for this purpose.
- Favor compiled extensions (tcllibc, twapi) when available, but always provide scripted fallbacks.
- Favor compiled extensions (tcllibc, twapi) when available, but provide scripted fallbacks whenever possible.
- Be mindful of long-running pipelines; chunk work and avoid blocking the Punk shell UI thread.
## Documentation & Comments
- Keep inline comments concise; describe intent, not mechanics.
- Update any relevant docs or usage notes in `scriptapps` when behavior changes.
- Primary documentation for procs should use the punk::args system, preferably within an argdoc sub namespace using: lappend PUNKARGS <listoftextblocks>
- Update any relevant docs or usage notes when behavior changes.
- Mention environment variables or flags required to run new features.
## Agent Workflow Tips
@ -158,8 +431,8 @@ Ensure module filenames include the version (`punk/console-0.1.1.tm`), and keep
## Final Submission Checklist
- [ ] Nested `AGENTS.md` files checked for scope-specific rules.
- [ ] `tcllint` (and `tcllint --fix` if needed) executed with clean results.
- [ ] Relevant tests (`tclsh scriptlib/tests/<file>.tcl`) executed and passing.
- [ ] Relevant tests (`tclsh src/tests/runtests.tcl`) executed and passing, or more specific `tclsh src/tests/modules/<modulehierarchypath>/tests/all.tcl` passing
- Treat implementation `.tcl` files in `src/lib/` as the source of truth for generic editable library behavior.
- Treat `src/lib_tcl<major>/` as Tcl-major-version-specific source trees.
- Prefer `src/lib/` unless version-specific behavior is relevant or the package exists only in a version-specific tree.
- Treat `pkgIndex.tcl` as a loader map unless the task is about package loading, registration, or load-path behavior.
- If a request begins from `pkgIndex.tcl`, resolve the mapped implementation file before analyzing or editing a proc.
- Prefer generic or version-specific source trees over built, installed, VFS, project layout, or generated copies unless the user explicitly targets those copies.
- This tree holds source specific to Tcl major version 8.
- Prefer this tree only when the package or proc is specific to Tcl major version 8 or only exists here.
- Do not prefer this tree when an equivalent generic source exists in the corresponding non-version-specific tree unless version-specific behavior is relevant.
- This tree holds source specific to Tcl major version 9.
- Prefer this tree only when the package or proc is specific to Tcl major version 9 or only exists here.
- Do not prefer this tree when an equivalent generic source exists in the corresponding non-version-specific tree unless version-specific behavior is relevant.
- Treat `src/modules/` as the source of truth for generic editable Punk modules.
- Expect the literal suffix `-999999.0a1.0.tm`.
- Treat `src/modules_tcl<major>/` as Tcl-major-version-specific source trees.
- If the same proc exists in both `src/modules/` and `src/modules_tcl<major>/`, prefer `src/modules/` unless version-specific behavior is relevant or only the version-specific file is active.
- Treat bootstrap, VFS, project layout, built, and installed copies as downstream unless the user explicitly targets them or the task is about bootstrap or packaging behavior.
- This tree holds source specific to Tcl major version 8.
- Prefer this tree only when the package or proc is specific to Tcl major version 8 or only exists here.
- Do not prefer this tree when an equivalent generic source exists in the corresponding non-version-specific tree unless version-specific behavior is relevant.
- This tree holds source specific to Tcl major version 9.
- Prefer this tree only when the package or proc is specific to Tcl major version 9 or only exists here.
- Do not prefer this tree when an equivalent generic source exists in the corresponding non-version-specific tree unless version-specific behavior is relevant.