The Challenge
How does npx oneie agent set up your project without asking questions? It reads your environment.
But environments are messy:
- Git might not be configured
- Environment variables might be missing
- package.json might not exist
- README might be incomplete
The solution: A multi-source priority chain that checks everywhere and uses the best available information.
The Detection System
Architecture
Priority Chain (highest to lowest):
1. Explicit CLI flags
2. Claude Code environment variables
3. Git configuration
4. Standard environment variables
5. Project files (package.json, README.md)
6. Directory inspection
7. Safe defaults
Key principle: Higher priority sources override lower ones. This lets users explicitly override any auto-detected value.
User Identity Detection
The Priority Chain
1. Explicit CLI Flags (Highest Priority)
npx oneie agent \
--name="Alice Johnson" \
--email="[email protected]"
Why this wins:
- User explicitly provided values
- No ambiguity
- Takes precedence over everything
2. Claude Code Context
npx oneie agent \
--claude-user="Alice Johnson" \
--claude-email="[email protected]"
How Claude Code provides this:
// Claude Code sets environment variables:
process.env.CLAUDE_USER_NAME = "Alice Johnson"
process.env.CLAUDE_USER_EMAIL = "[email protected]"
// CLI reads them automatically
const name = process.env.CLAUDE_USER_NAME
const email = process.env.CLAUDE_USER_EMAIL
Why this works:
- Claude Code knows your identity from login
- Passes context automatically
- No manual configuration needed
3. Git Configuration
git config user.name # "Alice Johnson"
git config user.email # "[email protected]"
Why this is reliable:
- Developers configure git for commits
- Values are verified (commits require them)
- Consistent across all projects
4. Environment Variables
export GIT_AUTHOR_NAME="Alice Johnson"
export GIT_AUTHOR_EMAIL="[email protected]"
Why these exist:
- CI/CD sets these for builds
- Git uses them when config missing
- Standard across all systems
5. Safe Defaults (Last Resort)
name: "Developer"
email: "dev@localhost"
Why we need defaults:
- Fresh VM with no configuration
- Docker containers
- Temporary environments
Result: Always succeeds, never blocks.
Detection Code
export async function detectUserIdentity(): Promise<UserIdentity> {
// 1. Check CLI flags (highest priority)
const nameFlag = getCliArg("--name");
const emailFlag = getCliArg("--email");
if (nameFlag || emailFlag) {
return {
name: nameFlag || "Developer",
email: emailFlag || "dev@localhost"
};
}
// 2. Check Claude context flags
const claudeUser = getCliArg("--claude-user");
const claudeEmail = getCliArg("--claude-email");
if (claudeUser) {
return {
name: claudeUser,
email: claudeEmail || "dev@localhost"
};
}
// 3. Check Claude environment variables
if (process.env.CLAUDE_USER_NAME) {
return {
name: process.env.CLAUDE_USER_NAME,
email: process.env.CLAUDE_USER_EMAIL || "dev@localhost"
};
}
// 4. Try git config
const gitName = await execCommand("git config user.name");
const gitEmail = await execCommand("git config user.email");
if (gitName && gitEmail) {
return { name: gitName.trim(), email: gitEmail.trim() };
}
// 5. Try standard environment variables
if (process.env.GIT_AUTHOR_NAME) {
return {
name: process.env.GIT_AUTHOR_NAME,
email: process.env.GIT_AUTHOR_EMAIL || "dev@localhost"
};
}
// 6. Fallback to defaults
return {
name: "Developer",
email: "dev@localhost"
};
}
Organization Detection
The Priority Chain
1. Explicit CLI Flag (Highest Priority)
npx oneie agent --org="Acme Corporation"
Why this wins:
- User knows their organization best
- No ambiguity
- Override everything
2. Claude Code Context
npx oneie agent --claude-org="Acme Corporation"
How Claude Code provides this:
process.env.CLAUDE_ORG_NAME = "Acme Corporation"
// CLI reads automatically
const org = process.env.CLAUDE_ORG_NAME
Why this works:
- Claude Code knows which organization you belong to
- Passes context to all tools
- Consistent across all sessions
3. Git Remote URL
git remote get-url origin
# https://github.com/acme-corp/my-project
Extraction logic:
// Extract organization from GitHub URL
const url = "https://github.com/acme-corp/my-project";
const match = url.match(/github\.com\/([^\/]+)/);
const org = match[1]; // "acme-corp"
// Convert to readable name
const orgName = org
.split("-")
.map(word => word.charAt(0).toUpperCase() + word.slice(1))
.join(" ");
// "Acme Corp"
Why this works:
- Most projects hosted on GitHub
- Organization in URL structure
- Reliable and consistent
4. package.json Fields
{
"author": "Acme Corporation",
"organization": "Acme Corporation",
"name": "@acme/my-project"
}
Extraction logic:
// Check multiple fields
const pkg = JSON.parse(fs.readFileSync("package.json"));
// 1. Author name
if (typeof pkg.author === "string") {
return pkg.author; // "Acme Corporation"
}
// 2. Author object
if (pkg.author?.name) {
return pkg.author.name;
}
// 3. Organization field
if (pkg.organization) {
return pkg.organization;
}
// 4. Scoped package name
if (pkg.name?.startsWith("@")) {
const scope = pkg.name.split("/")[0].slice(1);
return scope; // "acme"
}
Why this works:
- Standard npm metadata
- Required for publishing
- Project-specific
5. README.md First H1
# Acme Corporation
Building the future of...
Extraction logic:
const readme = fs.readFileSync("README.md", "utf-8");
const match = readme.match(/^#\s+(.+)$/m);
const org = match?.[1]; // "Acme Corporation"
Why this works:
- Most READMEs start with project/org name
- Human-readable
- Visible in GitHub
6. Parent Directory Name
/Users/alice/projects/acme-project/
^^^^^^^^^^^^
Use this as org name
Why this works:
- Developers name folders meaningfully
- Last resort when nothing else available
- Better than βDefault Organizationβ
7. Safe Default (Last Resort)
org: "Default Organization"
Why we need defaults:
- Fresh checkout with no metadata
- Testing environments
- Always completes successfully
Detection Code
export async function detectOrganization(basePath: string): Promise<string> {
// 1. Check CLI flag
const orgFlag = getCliArg("--org");
if (orgFlag) return orgFlag;
// 2. Check Claude context
const claudeOrg = getCliArg("--claude-org");
if (claudeOrg) return claudeOrg;
// 3. Check Claude environment variable
if (process.env.CLAUDE_ORG_NAME) {
return process.env.CLAUDE_ORG_NAME;
}
// 4. Try git remote
const gitRemote = await execCommand("git remote get-url origin");
if (gitRemote) {
const match = gitRemote.match(/github\.com\/([^\/]+)/);
if (match) {
return formatOrgName(match[1]);
}
}
// 5. Try package.json
const pkgPath = path.join(basePath, "package.json");
if (fs.existsSync(pkgPath)) {
const pkg = JSON.parse(fs.readFileSync(pkgPath, "utf-8"));
if (typeof pkg.author === "string") return pkg.author;
if (pkg.author?.name) return pkg.author.name;
if (pkg.organization) return pkg.organization;
if (pkg.name?.startsWith("@")) {
const scope = pkg.name.split("/")[0].slice(1);
return formatOrgName(scope);
}
}
// 6. Try README.md
const readmePath = path.join(basePath, "README.md");
if (fs.existsSync(readmePath)) {
const readme = fs.readFileSync(readmePath, "utf-8");
const match = readme.match(/^#\s+(.+)$/m);
if (match) return match[1];
}
// 7. Use directory name
const dirName = path.basename(basePath);
if (dirName !== "." && dirName !== "/") {
return formatOrgName(dirName);
}
// 8. Fallback to default
return "Default Organization";
}
Website Detection
The Priority Chain
1. Explicit CLI Flag
npx oneie agent --website="https://acme.com"
2. package.json Homepage
{
"homepage": "https://acme.com"
}
3. README.md First URL
# Acme Corporation
Visit us at https://acme.com
Extraction:
const readme = fs.readFileSync("README.md", "utf-8");
const match = readme.match(/https?:\/\/[^\s\)]+/);
const website = match?.[0]; // "https://acme.com"
4. Convert Git Remote to GitHub URL
// Git remote: [email protected]:acme-corp/project.git
// Convert to: https://github.com/acme-corp/project
const gitUrl = await execCommand("git remote get-url origin");
const website = gitUrl
.replace("[email protected]:", "https://github.com/")
.replace(".git", "");
5. No Website (Optional Field)
website: undefined // OK to omit
Performance Optimization
Parallel Detection
// Run all detections in parallel
const [user, org, website] = await Promise.all([
detectUserIdentity(),
detectOrganization(basePath),
detectWebsite(basePath)
]);
Result: All detection completes in < 500ms.
Caching Results
// Cache git commands (expensive)
let gitConfigCache: Map<string, string> = new Map();
async function getGitConfig(key: string): Promise<string> {
if (gitConfigCache.has(key)) {
return gitConfigCache.get(key)!;
}
const value = await execCommand(`git config ${key}`);
gitConfigCache.set(key, value);
return value;
}
Error Handling
async function execCommand(cmd: string): Promise<string> {
try {
const { stdout } = await exec(cmd);
return stdout.trim();
} catch (error) {
// Git not configured? Return empty string
// Detection chain continues to next source
return "";
}
}
Result: Errors donβt stop detection. Falls through to next source.
Real-World Examples
Example 1: Claude Code User
Environment:
CLAUDE_CODE=true
CLAUDE_USER_NAME="Sarah Chen"
CLAUDE_USER_EMAIL="[email protected]"
CLAUDE_ORG_NAME="TechStartup Inc"
Detection Result:
{
user: {
name: "Sarah Chen",
email: "[email protected]"
},
org: "TechStartup Inc",
website: undefined // Falls through to package.json/README
}
Why: Claude context wins (priority #2 for all fields).
Example 2: Git-Configured Developer
Environment:
git config user.name # "Bob Smith"
git config user.email # "[email protected]"
git remote get-url origin # https://github.com/bob-freelance/client-project
package.json:
{
"name": "client-website",
"homepage": "https://clientco.com"
}
Detection Result:
{
user: {
name: "Bob Smith",
email: "[email protected]"
},
org: "Bob Freelance", // From git remote
website: "https://clientco.com" // From package.json
}
Why: Git config wins for user (priority #3), git remote wins for org (priority #4), package.json wins for website (priority #2).
Example 3: Fresh VM
Environment:
# No git config
# No environment variables
# No package.json
# No README
Directory: /home/ubuntu/my-awesome-project/
Detection Result:
{
user: {
name: "Developer",
email: "dev@localhost"
},
org: "My Awesome Project", // From directory name
website: undefined
}
Why: Defaults win when nothing else available.
Example 4: CI/CD Pipeline
Environment:
CI=true
GIT_AUTHOR_NAME="GitHub Actions"
GIT_AUTHOR_EMAIL="[email protected]"
GITHUB_REPOSITORY="acme-corp/web-app"
Detection Result:
{
user: {
name: "GitHub Actions",
email: "[email protected]"
},
org: "Acme Corp", // Extracted from GITHUB_REPOSITORY
website: "https://github.com/acme-corp/web-app"
}
Why: Environment variables win for user (priority #5), GitHub URL wins for org and website.
Testing Detection
Dry Run Mode
npx oneie agent --dry-run
Output:
π Context Detection Results:
User:
Name: Alice Johnson
Email: [email protected]
Source: git config
Organization:
Name: Acme Corporation
Slug: acme-corporation
Source: git remote (github.com/acme-corp/project)
Website:
URL: https://acme.com
Source: package.json homepage
π What would be created:
/one/ directory (41 docs)
/.claude/ directory (agents, commands)
/acme-corporation/ directory
.env.local (updated with org settings)
.gitignore (updated to exclude install folder)
β οΈ Dry run mode: No files were created/modified
Verbose Mode
npx oneie agent --verbose
Output:
π€ Agent Environment Detected: Claude Code
π Detecting context...
User Identity Detection:
β
CLI flags: Not provided
β
Claude flags: Not provided
β
Claude env vars: Found!
CLAUDE_USER_NAME = "Alice Johnson"
CLAUDE_USER_EMAIL = "[email protected]"
β© Skipped: git config (already found)
β© Skipped: env vars (already found)
Organization Detection:
β
CLI flag: Not provided
β
Claude flag: Not provided
β
Claude env var: Not found
β
Git remote: Found!
URL: https://github.com/acme-corp/project
Org: acme-corp β Acme Corp
β© Skipped: package.json (already found)
Website Detection:
β
CLI flag: Not provided
β
package.json: Found!
Homepage: https://acme.com
β© Skipped: README (already found)
β
Context Detection Complete (421ms)
Why This Approach Works
1. Graceful Degradation
Each source is optional. If one fails, try the next. Always succeeds.
2. Explicit Overrides
Users can always override auto-detection with flags. Maximum control.
3. Zero Manual Input
Never prompts. Never blocks. Fully automated.
4. Predictable Priority
Highest priority always wins. No ambiguity.
5. Fast Execution
Parallel detection + caching = < 500ms. Imperceptible to users.
Future Enhancements
v3.7.0
- Detect multiple organizations (monorepo support)
- Read organization from
.onercconfig file - Support custom detection scripts
v4.0.0
- Machine learning-based name normalization
- Organization registry (validate against known orgs)
- Confidence scoring for each detection source
Try It Yourself
# Test detection without creating files
npx oneie agent --dry-run
# See detailed detection process
npx oneie agent --verbose
# Override any detected value
npx oneie agent --name="Your Name" --org="Your Org"
Key Takeaways
- π Priority chain - Higher priority sources override lower ones
- π― Multiple sources - Always has fallback options
- β‘ Fast execution - Parallel detection in < 500ms
- π‘οΈ Never blocks - Errors fall through to next source
- π§ Always overrideable - Users have final control
- π€ AI-friendly - Claude Code passes context automatically
- π Universal - Works in any environment (dev, CI/CD, fresh VM)
Smart detection. Zero interaction. Always succeeds.
π§ ONE Platform - Intelligence Built In