@pasynkov/harness
v0.2.0
Published
Parness — Pasynkov's Harness. Sets up a configured agent harness in one command.
Maintainers
Readme
Parness — Pasynkov's Harness
Sets up a configured agent harness in one command.
npx @pasynkov/harness██████ ██ ██ Parness
██ ██ ██ ██ Pasynkov's Harness
██████ ██████
██ ██ ██ Sets up:
██ ██ ██ CLAUDE.md · permissions · spec-driven setup
Enter to continueWhat it does
- Asks where to set up: the current directory, a new one, or one you pick in a browser.
- Asks for a target tool. Claude Code today; Cursor and Codex are placeholders.
- Asks for a spec-driven framework — OpenSpec, Spec Kit, or none — and delegates to that framework's own installer, so you always get its current version.
- Writes
CLAUDE.mdand.claude/settings.local.jsoninto the chosen directory. - Offers to start Claude Code there.
Nothing outside the target directory is read or written, apart from creating the target itself.
User-level configuration under ~/.claude is never touched.
Choosing a directory
Pass a path to skip the question entirely. Missing directories are created, parents included:
npx @pasynkov/harness ./my-app
npx @pasynkov/harness --dir work/experiments/fooWithout a path you get a menu:
? Where
› Current ~/dev/private/harness
Create new…
Browse…Create new… takes a name, resolves it against the current directory, and shows the absolute
path before creating anything. Browse… walks the filesystem — ↑↓ to move, → to open, ←
to go up, h to show hidden directories — and offers use this directory and
create new here… at the bottom of every listing.
The filesystem root, your home directory itself, paths that are files, and directories you cannot write to are refused. Directories under your home are fine.
Starting Claude Code
Because a process cannot change its parent shell's directory, the CLI prints cd <target> and
then offers to start Claude Code in the target directory instead. Leaving Claude Code returns
you to the shell you started from. The offer never appears in unattended runs unless you pass
--launch, and it is skipped when claude is not on PATH.
Existing files
CLAUDE.md prompts for overwrite, skip, or backup. .claude/settings.local.json is merged:
the union of permissions.allow and permissions.deny, duplicates removed, every other key
preserved.
Flags
| Flag | Meaning |
| --- | --- |
| [path] | Directory to set up, created if missing |
| --dir <path> | Same as the positional argument; giving both a different path is an error |
| --target <name> | Target tool: claude |
| --sdd <name> | Framework: openspec, speckit, none |
| --yes | Accept defaults, never prompt; targets the current directory when no path is given |
| --force | Overwrite existing files instead of skipping them |
| --launch | Start Claude Code afterwards even without prompting |
npx @pasynkov/harness ./my-app --target claude --sdd openspec --yesPermissions it writes
The preset is deliberately permissive — this is a personal harness, optimised for never being interrupted by a permission prompt:
{
"permissions": {
"allow": ["Bash(*)", "WebSearch", "WebFetch(domain:*)", "Agent(*)", "Skill(*)"],
"deny": ["Read(./.env)", "Read(./.env.*)"]
}
}Bash(*) allows any shell command without asking, including downloading and running code from
the network. The .env deny rules also hide those files from file discovery, not just from
direct reads.
Requirements
- Node 18+
uvonPATHfor Spec Kit; without it that option is shown disabled
