Skip to content

fix(cli): wire up --template flag so advertised templates actually apply - #12

Open
jodunk wants to merge 1 commit into
NikitaDmitrieff:mainfrom
jodunk:fix/cli-template-flag
Open

fix(cli): wire up --template flag so advertised templates actually apply#12
jodunk wants to merge 1 commit into
NikitaDmitrieff:mainfrom
jodunk:fix/cli-template-flag

Conversation

@jodunk

@jodunk jodunk commented Jul 23, 2026

Copy link
Copy Markdown

Problem

init() only took a project name, so --template was silently dropped:

npx create-auto-co my-saas --template saas

The README advertises three templates (saas, docs-site, api-backend), and those template files (template.conf, mission.md, consensus-next-action.md) ship in the repo — but nothing in the CLI read them. Users got the generic scaffold regardless of the flag. False advertising on the primary install path, live on main today.

Fix

Parse --template, then for the chosen template:

  • read template.conf (DESCRIPTION, EXTRA_DIRS)
  • inject mission.md into the cloned CLAUDE.md ## Mission section
  • use consensus-next-action.md as the Day-0 ## Next Action
  • set ## Company State > Product from DESCRIPTION
  • create EXTRA_DIRS after the metaFiles cleanup (so a declared dir like projects/landing isn't deleted by the existing landing-project removal — this is the one non-obvious ordering point)
  • clean templates/ from the scaffold like the other meta files

REPO is now overridable via AUTO_CO_REPO so the flag can be exercised against a local clone in tests.

Test

tests/test-cli-template.sh — self-contained (stubs claude, clones the repo as a stand-in origin). Asserts the saas template lands its mission in CLAUDE.md, its Next Action in consensus.md, creates projects/app + projects/landing, and removes templates/:

Results: 5 passed, 0 failed

Runnable standalone (bash tests/test-cli-template.sh); auto-discovered by run-all.sh via the tests/test-*.sh glob once that harness lands. No overlap with the reliability PRs.

Scope

  • cli/bin/auto-co.js — arg parsing + template application (+89)
  • README.md — clarifies templates preconfigure mission + stack direction (agents build toward them), not an instant stack scaffold
  • tests/test-cli-template.sh — new regression guard

🤖 Generated with Claude Code

Summary by CodeRabbit

  • New Features

    • Added optional project templates to CLI scaffolding: saas, docs-site, and api-backend.
    • Templates can configure the project mission, product direction, initial next action, and additional directories.
    • Added AUTO_CO_REPO support for overriding the repository source.
    • Updated CLI help with template usage details.
  • Documentation

    • Expanded README guidance describing how templates configure new projects.
  • Tests

    • Added coverage validating template-based project generation and expected scaffold contents.

The README advertised `npx create-auto-co my-saas --template saas` with three
templates (saas, docs-site, api-backend), and those template files
(template.conf, mission.md, consensus-next-action.md) ship in the repo -- but
init() only took a project name, so `--template` was silently dropped and users
got the generic scaffold regardless of the flag. False advertising on the
primary install path.

Fix: parse `--template`, read the chosen template's conf, inject its mission into
the cloned CLAUDE.md, and use its consensus Next Action + Product label for Day 0.
The template's EXTRA_DIRS are created AFTER the metaFiles cleanup (so a declared
dir like projects/landing isn't deleted by the existing landing-project removal).
templates/ is then cleaned from the scaffold like the other meta files. REPO is
now overridable via AUTO_CO_REPO so the flag can be exercised against a local
clone in tests.

Adds tests/test-cli-template.sh (self-contained: stubs `claude`, clones the repo
as a stand-in origin) asserting the saas template lands its mission, Next Action,
extra dirs, and cleanup -- 5/5. Runnable standalone; picked up by run-all.sh
once that harness lands.

Co-Authored-By: Claude <noreply@anthropic.com>
@coderabbitai

coderabbitai Bot commented Jul 23, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

The CLI now accepts templates during project initialization, applies template configuration to scaffolded files and directories, removes template sources, and records template metadata. Documentation and a regression test cover the new scaffolding behavior.

Changes

Template scaffolding

Layer / File(s) Summary
Template CLI contract
cli/bin/auto-co.js
Adds --template help and parsing, supports AUTO_CO_REPO, and forwards the selected template through both initialization paths.
Template application during initialization
cli/bin/auto-co.js
Loads template configuration, updates CLAUDE.md and Day-0 consensus data, removes template sources, and creates declared directories.
Template behavior validation and documentation
README.md, tests/test-cli-template.sh
Documents template-driven project direction and verifies mission, consensus, directory, and cleanup outputs.

Estimated code review effort: 3 (Moderate) | ~25 minutes

Sequence Diagram(s)

sequenceDiagram
  participant Developer
  participant AutoCoCLI
  participant Repository
  participant Scaffold
  Developer->>AutoCoCLI: initialize project with --template
  AutoCoCLI->>Repository: clone repository
  AutoCoCLI->>Repository: read template.conf
  Repository-->>AutoCoCLI: template mission and metadata
  AutoCoCLI->>Scaffold: update CLAUDE.md and consensus
  AutoCoCLI->>Scaffold: remove templates and create extra directories
Loading
🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly summarizes the main change: wiring up the CLI --template flag so templates apply.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

🧹 Nitpick comments (1)
tests/test-cli-template.sh (1)

48-56: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Assert the configured Product label.

DESCRIPTIONCompany State > Product is part of this change, but this test never checks it. Read the expected DESCRIPTION from the source template (or use a fixed expected value) and assert it appears in memories/consensus.md.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@tests/test-cli-template.sh` around lines 48 - 56, Extend the CLI template
test around the existing consensus assertions to verify the configured Product
label from DESCRIPTION appears in $P/memories/consensus.md. Read the expected
value from the source template or use the change’s fixed expected label, then
assert its presence without altering the existing scaffold checks.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@cli/bin/auto-co.js`:
- Around line 214-217: Validate each path in the tpl.extraDirs loop before
calling mkdirSync: reject absolute paths and resolve it against target, ensuring
the resolved directory remains beneath the target scaffold root. Only create
directories that pass both checks, using the validated resolved path rather than
the raw template value.
- Line 330: The init argument parsing must ignore the --template option and its
value when selecting the project name. Update the init handling at
cli/bin/auto-co.js lines 330-330 and unknown-argument handling at
cli/bin/auto-co.js lines 356-356 to derive the name from the first non-template
positional argument, while preserving optional-name behavior.
- Line 8: Update the clone invocation in the auto-co startup flow to avoid
interpolating REPO into a shell command. Use the existing spawn or spawnSync API
with git clone arguments passed as an array, preserving AUTO_CO_REPO as a
literal repository URL and keeping the current command behavior.

---

Nitpick comments:
In `@tests/test-cli-template.sh`:
- Around line 48-56: Extend the CLI template test around the existing consensus
assertions to verify the configured Product label from DESCRIPTION appears in
$P/memories/consensus.md. Read the expected value from the source template or
use the change’s fixed expected label, then assert its presence without altering
the existing scaffold checks.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: cf383086-989b-4f1d-be39-e5ea98b2929a

📥 Commits

Reviewing files that changed from the base of the PR and between 5e6bb8a and 10af85c.

📒 Files selected for processing (3)
  • README.md
  • cli/bin/auto-co.js
  • tests/test-cli-template.sh

Comment thread cli/bin/auto-co.js

const VERSION = "1.1.1";
const REPO = "https://github.com/NikitaDmitrieff/auto-co-meta.git";
const REPO = process.env.AUTO_CO_REPO || "https://github.com/NikitaDmitrieff/auto-co-meta.git";

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔒 Security & Privacy | 🟡 Minor | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

ast-grep outline cli/bin/auto-co.js --items all
ast-grep run --pattern 'function run($$$) { $$$ }' --lang javascript cli/bin/auto-co.js
rg -nP -C3 '^(?:function\s+run\b|const\s+run\s*=|let\s+run\s*=|import\s+.*\brun\b)|git clone --depth 1|AUTO_CO_REPO' cli/bin/auto-co.js

Repository: NikitaDmitrieff/auto-co-meta

Length of output: 2205


🏁 Script executed:

#!/bin/bash
set -euo pipefail

node - <<'JS'
const { spawnSync } = require("child_process");

const targets = [
  "/tmp/injection-safe-dir",
  `"; git status; ls > /tmp/auto-co-injection-marker", "bad-name`,
  `", git status; ls > /tmp/auto-co-injection-marker", "bad-name`
];

console.log("command_string_simulation_results");
for (const repo of targets) {
  try {
    const { status, stdout, stderr } = spawnSync("/bin/bash", ["-c", `git clone --depth 1 ${repo} "/dev/null"`], { stdio: ["ignore", "pipe", "pipe"], timeout: 5000 });
    console.log(JSON.stringify({
      repo,
      status,
      stdout: stdout?.toString().slice(0, 120),
      stderr: stderr?.toString().slice(0, 240),
      marked: require("fs").existsSync("/tmp/auto-co-injection-marker")
    }));
  } catch (e) {
    console.log(`repo:${JSON.stringify(repo)}_error:${e.message}`);
  }
}
console.log("\nargument_array_safe_simulation_results");
for (const repo of targets) {
  const target = "/tmp/injection-safe-dir";
  try {
    const { status, stdout, stderr } = spawnSync("git", ["clone", "--depth", "1", repo, target], { stdio: ["ignore", "pipe", "pipe"], timeout: 5000 });
    console.log(JSON.stringify({
      repo,
      status,
      stdout: stdout?.toString().slice(0, 120),
      stderr: stderr?.toString().slice(0, 240),
      marked: require("fs").existsSync("/tmp/auto-co-injection-marker")
    }));
  } catch (e) {
    console.log(`repo:${JSON.stringify(repo)}_error:${e.message}`);
  }
}
JS

printf '\nRelevant auto-co.js slice:\n'
sed -n '1,160p' cli/bin/auto-co.js

printf '\nRepository marker cleanup:\n'
rm -f /tmp/auto-co-injection-marker

Repository: NikitaDmitrieff/auto-co-meta

Length of output: 7091


Pass the repository URL to git clone as an argument.

REPO is interpolated into a shell command via run(), so a crafted AUTO_CO_REPO can escape as shell syntax. Use the existing spawn import or spawnSync with an argument array so the URL cannot execute injected commands.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@cli/bin/auto-co.js` at line 8, Update the clone invocation in the auto-co
startup flow to avoid interpolating REPO into a shell command. Use the existing
spawn or spawnSync API with git clone arguments passed as an array, preserving
AUTO_CO_REPO as a literal repository URL and keeping the current command
behavior.

Comment thread cli/bin/auto-co.js
Comment on lines +214 to +217
// Template-declared dirs (created AFTER cleanup so metaFiles can't remove them).
for (const d of tpl.extraDirs) {
mkdirSync(resolve(target, d), { recursive: true });
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔒 Security & Privacy | 🟡 Minor | ⚡ Quick win

Keep template paths inside the scaffold.

EXTRA_DIRS is used as a raw path, so ../outside or an absolute path can create directories outside target. Reject absolute paths and verify each resolved path remains beneath the scaffold root.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@cli/bin/auto-co.js` around lines 214 - 217, Validate each path in the
tpl.extraDirs loop before calling mkdirSync: reject absolute paths and resolve
it against target, ensuring the resolved directory remains beneath the target
scaffold root. Only create directories that pass both checks, using the
validated resolved path rather than the raw template value.

Comment thread cli/bin/auto-co.js
switch (cmd) {
case "init":
init(args[1]);
init(args[1], parseTemplateArg(args));

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Do not treat --template as the project name.

Because the name is optional, auto-co init --template saas scaffolds ./--template; the direct invocation has the same failure. Derive the project name from the first non-template positional argument.

  • cli/bin/auto-co.js#L330-L330: exclude --template and its value before selecting the init name.
  • cli/bin/auto-co.js#L356-L356: exclude template-option tokens before treating an unknown first argument as the project name.
📍 Affects 1 file
  • cli/bin/auto-co.js#L330-L330 (this comment)
  • cli/bin/auto-co.js#L356-L356
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@cli/bin/auto-co.js` at line 330, The init argument parsing must ignore the
--template option and its value when selecting the project name. Update the init
handling at cli/bin/auto-co.js lines 330-330 and unknown-argument handling at
cli/bin/auto-co.js lines 356-356 to derive the name from the first non-template
positional argument, while preserving optional-name behavior.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant